home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume12 / cake / part02 < prev    next >
Encoding:
Internet Message Format  |  1987-10-14  |  61.8 KB

  1. Subject:  v12i008:  Cake, a make replacement, Part02/09
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: Zoltan Somogyi <zs@munnari.oz>
  7. Posting-number: Volume 12, Issue 8
  8. Archive-name: cake/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create:
  15. #    act.c
  16. #    chase.c
  17. #    entry.c
  18. #    error.c
  19. #    expand.c
  20. #    file.c
  21. # This archive created: Wed Oct 14 21:08:43 1987
  22. export PATH; PATH=/bin:/usr/bin:$PATH
  23. echo shar: "extracting 'act.c'" '(12578 characters)'
  24. if test -f 'act.c'
  25. then
  26.     echo shar: "will not over-write existing file 'act.c'"
  27. else
  28. sed 's/^X//' << \SHAR_EOF > 'act.c'
  29. X/*
  30. X**    Module to execute Cake actions.
  31. X*/
  32. X
  33. Xstatic    char
  34. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/act.c,v 1.14 86/07/19 12:22:18 zs Exp $";
  35. X
  36. X#include    "cake.h"
  37. X
  38. X/*
  39. X**    Update the node by executing the attached actions.
  40. X**    Actually, all the buddies will be updated, and
  41. X**    no action will be executed unless it is necessary.
  42. X**
  43. X**    The level of a file is one greater than the level of its
  44. X**    parent in the chase graph; the level of !MAINCAKE! is 0.
  45. X**    This controls the printing of messages about the primary
  46. X**    targets.
  47. X*/
  48. X
  49. Xupdate(node, level, force_exec)
  50. Xreg    Node    *node;
  51. Xreg    int    level;
  52. Xreg    bool    force_exec;
  53. X{
  54. X    extern        get_utime();
  55. X    extern        save_novol();
  56. X    extern    bool    diff_novol();
  57. X    extern    Wait    carry_out();
  58. X    extern    char    *list_names();
  59. X    reg    Node    *bnode, *onode;
  60. X    reg    List    *ptr, *ptr1;
  61. X    reg    bool    oksofar, needact, mayskip;
  62. X    reg    List    *errnodes;
  63. X    Wait        code;
  64. X
  65. X    put_trail("update", "start");
  66. X    cdebug("hunting %s at level %d\n", node->n_name, level);
  67. X
  68. X    /* force printing of "up-to-date" messages */
  69. X    if (level == 0 && is_ok(node))
  70. X        node->n_kind = n_CANDO;
  71. X        
  72. X    if (off_node(node, nf_ERR) && is_ok(node))
  73. X    {
  74. X        cdebug("everything a-ok, nothing to do\n");
  75. X        if (level == 1)
  76. X        {
  77. X            if (on_node(node, nf_ORIG))
  78. X            {
  79. X                printf("cake: target %s has no ancestors\n", node->n_name);
  80. X                node->n_kind = n_NOWAY;
  81. X            }
  82. X            or (! xflag)
  83. X                printf("cake: %s is up to date\n", node->n_name);
  84. X        }
  85. X
  86. X        put_trail("update", "finish");
  87. X        return;
  88. X    }
  89. X
  90. X#ifdef    CAKEDEBUG
  91. X    if (cakedebug)
  92. X    {
  93. X        printf("starting update of\n");
  94. X        print_node(node);
  95. X    }
  96. X#endif
  97. X
  98. X    if (on_node(node, nf_ERR))
  99. X    {
  100. X        trace_errs(node);
  101. X        return;
  102. X    }
  103. X
  104. X    errnodes = NULL;
  105. X
  106. X    /* skip the actions if they are useless or not needed */
  107. X    oksofar = TRUE;
  108. X    needact = FALSE;
  109. X    mayskip = FALSE;
  110. X    for_list (ptr, node->n_new)
  111. X    {
  112. X        bnode  = (Node *) ldata(ptr);
  113. X
  114. X        if (on_node(bnode, nf_ERR))
  115. X        {
  116. X            oksofar = FALSE;
  117. X            errnodes = addtail(errnodes, bnode);
  118. X        }
  119. X        else
  120. X        {
  121. X            if (off_node(bnode, nf_EXIST) || bnode->n_rtime < bnode->n_utime)
  122. X                needact = TRUE;
  123. X            
  124. X            if (on_node(bnode, nf_DEPNONVOL))
  125. X                mayskip = TRUE;
  126. X        }
  127. X    }
  128. X
  129. X    if (! oksofar)
  130. X    {
  131. X        cdebug("error in buddies\n");
  132. X        if (vflag && strdiff(node->n_name, CHASEROOT))
  133. X        {
  134. X            sprintf(scratchbuf, "cannot proceed with update of %s because of problems with %s %s",
  135. X                node->n_name, (length(errnodes) == 1)? "buddy": "buddies", list_names(errnodes));
  136. X            add_error(node, new_name(scratchbuf), errnodes, TRUE);
  137. X            trace_errs(node);
  138. X        }
  139. X
  140. X        goto endit;
  141. X    }
  142. X
  143. X    if (! needact)
  144. X    {
  145. X        cdebug("no need for actions\n");
  146. X        if (strdiff(node->n_name, CHASEROOT))
  147. X            printf("cake: %s is up to date\n", node->n_name);
  148. X
  149. X        goto endit;
  150. X    }
  151. X
  152. X    /* update all ancestors of all buddies */
  153. X    for_list (ptr, node->n_new)
  154. X    {
  155. X        bnode  = (Node *) ldata(ptr);
  156. X        for_list (ptr1, bnode->n_old)
  157. X        {
  158. X            onode = (Node *) ldata(ptr1);
  159. X            update(onode, level+1, force_exec);
  160. X            if (on_node(onode, nf_ERR) || ! is_ok(onode))
  161. X            {
  162. X                oksofar = FALSE;
  163. X                errnodes = addtail(errnodes, onode);
  164. X            }
  165. X        }
  166. X    }
  167. X
  168. X    /* skip the actions if any ancestors are missing */
  169. X    if (! oksofar)
  170. X    {
  171. X        cdebug("error in prerequisites\n");
  172. X        if (vflag && strdiff(node->n_name, CHASEROOT))
  173. X        {
  174. X            sprintf(scratchbuf, "cannot proceed with update of %s because of problems with %s %s",
  175. X                node->n_name, (length(errnodes) == 1)? "ancestor": "ancestors", list_names(errnodes));
  176. X            add_error(node, new_name(scratchbuf), errnodes, TRUE);
  177. X            trace_errs(node);
  178. X        }
  179. X
  180. X        goto endit;
  181. X    }
  182. X
  183. X    /* skip the actions; node is a missing base file */
  184. X    if (is_noway(node))
  185. X    {
  186. X        cdebug("error in planning\n");
  187. X        trace_errs(node);
  188. X        goto endit;
  189. X    }
  190. X
  191. X    /* find any NOWAY buddies; these may have n_old == [] */
  192. X    for_list (ptr, node->n_new)
  193. X    {
  194. X        bnode  = (Node *) ldata(ptr);
  195. X        if (is_noway(bnode))
  196. X        {
  197. X            oksofar = FALSE;
  198. X            errnodes = addtail(errnodes, bnode);
  199. X        }
  200. X    }
  201. X
  202. X    /* skip the actions if there are any NOWAY buddies */
  203. X    if (! oksofar)
  204. X    {
  205. X        cdebug("error in buddy planning\n");
  206. X        sprintf(scratchbuf, "dare not update %s because of possible effects on %s %s", node->n_name,
  207. X            (length(errnodes) == 1)? "buddy": "buddies", list_names(errnodes));
  208. X        add_error(node, new_name(scratchbuf), LNULL, TRUE);
  209. X        trace_errs(node);
  210. X        goto endit;
  211. X    }
  212. X
  213. X    /* reevaluate the necessity to act in the light of the */
  214. X    /* actions taken to update possibly nonvolatile ancestors */
  215. X    if (mayskip)
  216. X    {
  217. X        needact = FALSE; /* assume so for the moment */
  218. X        cdebug("deciding whether to skip\n");
  219. X        for_list (ptr, node->n_new)
  220. X        {
  221. X            bnode  = (Node *) ldata(ptr);
  222. X
  223. X            if (on_node(bnode, nf_DEPNONVOL))
  224. X            {
  225. X                cdebug("considering %s\n", bnode->n_name);
  226. X                get_utime(bnode, FALSE);
  227. X            }
  228. X
  229. X            if (off_node(bnode, nf_EXIST) || bnode->n_rtime < bnode->n_utime)
  230. X            {
  231. X                cdebug("%s needs action\n", bnode->n_name);
  232. X                needact = TRUE;
  233. X            }
  234. X        }
  235. X    }
  236. X
  237. X    if (! needact)
  238. X    {
  239. X        cdebug("no need for actions after all\n");
  240. X        if (strdiff(node->n_name, CHASEROOT))
  241. X            printf("cake: %s is up to date\n", node->n_name);
  242. X
  243. X        goto endit;
  244. X    }
  245. X
  246. X    if (tflag)
  247. X    {
  248. X        /* instead of action just touch the targets */
  249. X        for_list (ptr, node->n_new)
  250. X        {
  251. X            bnode = (Node *) ldata(ptr);
  252. X            if (on_node(bnode, nf_PSEUDO))
  253. X                continue;
  254. X
  255. X            if (rflag)
  256. X                cake_utimes(bnode, bnode->n_utime);
  257. X            else
  258. X                cake_utimes(bnode, GENESIS);
  259. X            
  260. X            printf("touch %s\n", bnode->n_name);
  261. X        }
  262. X    }
  263. X    else
  264. X    {
  265. X        /* prepare for actions */
  266. X        for_list (ptr, node->n_new)
  267. X        {
  268. X            bnode = (Node *) ldata(ptr);
  269. X            if (on_node(bnode, nf_NONVOL))
  270. X                save_novol(bnode);
  271. X        }
  272. X
  273. X        /* execute actions */
  274. X        code = carry_out(node, force_exec);
  275. X        if (code.w_status != 0)
  276. X        {
  277. X            oksofar = FALSE;
  278. X            sprintf(scratchbuf, "error in actions for %s", node->n_name);
  279. X            for_list (ptr, node->n_new)
  280. X            {
  281. X                bnode = (Node *) ldata(ptr);
  282. X                add_error(bnode, new_name(scratchbuf), LNULL, TRUE);
  283. X            }
  284. X
  285. X            if (! xflag)
  286. X            {
  287. X                if (code.w_termsig == 0)
  288. X                    printf("*** Error code %d\n", code.w_retcode);
  289. X                else
  290. X                    printf("*** Termination code %d\n", code.w_termsig);
  291. X            }
  292. X            
  293. X            cake_error(node);
  294. X            goto endit;
  295. X        }
  296. X
  297. X        /* clean up after actions */
  298. X        for_list (ptr, node->n_new)
  299. X        {
  300. X            bnode = (Node *) ldata(ptr);
  301. X            if (on_node(bnode, nf_NONVOL) && ! diff_novol(bnode))
  302. X                node_resetstat(bnode);
  303. X            or (rflag)
  304. X                node_setstat(bnode);
  305. X            else
  306. X                node_stat(bnode);
  307. X        }
  308. X    }
  309. X
  310. Xendit:
  311. X
  312. X    cdebug("update finished\n");
  313. X    for_list (ptr, node->n_new)
  314. X    {
  315. X        bnode = (Node *) ldata(ptr);
  316. X        if (oksofar)
  317. X        {
  318. X            if (on_node(bnode, nf_EXIST) || on_node(bnode, nf_PSEUDO) || nflag)
  319. X                bnode->n_kind = n_OK;
  320. X            else
  321. X            {
  322. X                set_node(bnode, nf_ERR);
  323. X                if (length(node->n_act) == 0)
  324. X                    sprintf(scratchbuf, "no actions to make %s with", bnode->n_name);
  325. X                else
  326. X                    sprintf(scratchbuf, "action did not create %s", bnode->n_name);
  327. X
  328. X                add_error(bnode, new_name(scratchbuf), LNULL, TRUE);
  329. X                trace_errs(bnode);
  330. X            }
  331. X        }
  332. X
  333. X#ifdef    CAKEDEBUG
  334. X        if (cakedebug)
  335. X            print_node(bnode);
  336. X#endif
  337. X    }
  338. X
  339. X    put_trail("update", "finish");
  340. X}
  341. X
  342. X/*
  343. X**    Execute the plan prepared by chase.c
  344. X**    Prevent the deletion of the primary targets by cleanup.
  345. X*/
  346. X
  347. Xexecute(root)
  348. Xreg    Node    *root;
  349. X{
  350. X    reg    List    *ptr;
  351. X    reg    Node    *target;
  352. X
  353. X    for_list (ptr, root->n_old)
  354. X    {
  355. X        target = (Node *) ldata(ptr);
  356. X        set_node(target, nf_NODELETE);
  357. X    }
  358. X
  359. X    update(root, 0, FALSE);
  360. X}
  361. X
  362. X/*
  363. X**    Carry out the specified actions and return the exit code.
  364. X**    Note that an empty list of actions is perfectly acceptable.
  365. X*/
  366. X
  367. X#define    START_SCRIPT    "{"
  368. X#define    FINISH_SCRIPT    "}"
  369. X
  370. XWait
  371. Xcarry_out(node, force_exec)
  372. Xreg    Node    *node;
  373. Xreg    bool    force_exec;
  374. X{
  375. X    extern    char    *expand_cmds();
  376. X    extern    Wait    action();
  377. X    reg    List    *ptr;
  378. X    reg    Act    *act;
  379. X    reg    Node    *bnode;
  380. X    Wait        code;
  381. X
  382. X    if (Gflag && ! nflag)
  383. X    {
  384. X        for_list (ptr, node->n_new)
  385. X        {
  386. X            bnode = (Node *) ldata(ptr);
  387. X            if (on_node(bnode, nf_EXIST))
  388. X            {
  389. X                cdebug("removing %s for -G\n", bnode->n_name);
  390. X                cake_remove(bnode->n_name);
  391. X            }
  392. X        }
  393. X    }
  394. X
  395. X    for_list (ptr, node->n_act)
  396. X    {
  397. X        act = (Act *) ldata(ptr);
  398. X
  399. X        if (nflag)
  400. X        {
  401. X            if (off_act(act, af_MINUSN) && ! force_exec)
  402. X                show_act(act->a_str, (char *) NULL);
  403. X            else
  404. X            {
  405. X                reset_act(act, af_SILENT);
  406. X                printf("executing ...\n");
  407. X                code = action(act, node);
  408. X                printf("... done\n");
  409. X                if (code.w_status != 0)
  410. X                    return code;
  411. X            }
  412. X
  413. X            continue;
  414. X        }
  415. X
  416. X        code = action(act, node);
  417. X        if (code.w_status != 0)
  418. X            return code;
  419. X    }
  420. X
  421. X    code.w_status = 0;
  422. X    return code;
  423. X}
  424. X
  425. X/*
  426. X**    Execute the given command and return its status,
  427. X**    modified by flags and prefixes.
  428. X*/
  429. X
  430. XWait
  431. Xaction(act, node)
  432. Xreg    Act    *act;
  433. Xreg    Node    *node;
  434. X{
  435. X    extern    int    cake_proc();
  436. X    extern    Wait    cake_wait();
  437. X    Wait        code;
  438. X    reg    A_kind    type;
  439. X    reg    int    pid;
  440. X    reg    char    *after;
  441. X
  442. X    put_trail("action", "start");
  443. X    after = expand_cmds(act->a_str);
  444. X    if (! (on_act(act, af_SILENT) || sflag))
  445. X        show_act(act->a_str, after);
  446. X    act->a_str = after;
  447. X
  448. X    if (on_act(act, af_SCRIPT))
  449. X        type = Script;
  450. X    or (on_act(act, af_SYSTEM))
  451. X        type = System;
  452. X    else
  453. X        type = Exec;
  454. X
  455. X    pid = cake_proc(act->a_str, type, (char *) NULL, node, (int (*)()) NULL, (List *) NULL);
  456. X    code = cake_wait(pid);
  457. X
  458. X    if (on_act(act, af_IGNORE) || iflag)
  459. X        code.w_status = 0;
  460. X
  461. X    if (code.w_status != 0 && ! kflag)
  462. X        exit_cake(FALSE);
  463. X
  464. X    put_trail("action", "finish");
  465. X    return code;
  466. X}
  467. X
  468. X/*
  469. X**    Print an action in the format specified by the options.
  470. X**    The two args are the action before and after expansion.
  471. X**    The second may be NULL, in which case show_act does the
  472. X**    expansion itself.
  473. X*/
  474. X
  475. Xshow_act(before, after)
  476. Xreg    char    *before;
  477. Xreg    char    *after;
  478. X{
  479. X    extern    char    *squeeze();
  480. X    reg    char    *form;
  481. X
  482. X    if (bflag)
  483. X        form = before;
  484. X    or (after != NULL)
  485. X        form = after;
  486. X    else
  487. X        form = expand_cmds(before);
  488. X
  489. X    if (wflag)
  490. X        printf("%s", form);
  491. X    else
  492. X        printf("%s", squeeze(form));
  493. X}
  494. X
  495. X/*
  496. X**    Reduce the width of the given command string
  497. X**    by squeezing out extra spaces and tabs.
  498. X*/
  499. X
  500. Xchar *
  501. Xsqueeze(cmd)
  502. Xreg    char    *cmd;
  503. X{
  504. X    char        buf[MAXSIZE];
  505. X    reg    char    *s;
  506. X    reg    int    i, oldi;
  507. X    reg    bool    inquotes;
  508. X    reg    bool    insingle;
  509. X    reg    bool    indouble;
  510. X    reg    bool    lastblank;
  511. X
  512. X    s = cmd;
  513. X    i = 0;
  514. X    lastblank = FALSE;
  515. X    while (*s != '\0')
  516. X    {
  517. X        while (*s != '\0' && (*s == ' ' || *s == '\t'))
  518. X            s++;
  519. X
  520. X        if (lastblank && (*s == '\n' || *s == '\r' || *s == '\f'))
  521. X            i--;
  522. X
  523. X        oldi = i;
  524. X        inquotes = FALSE;
  525. X        for (; *s != '\0' && ((*s != ' ' && *s != '\t') || inquotes); s++)
  526. X        {
  527. X            if (*s == '\\')
  528. X            {
  529. X                buf[i++] = *s;
  530. X                if (s[1] != '\0')
  531. X                    buf[i++] = *++s;
  532. X            }
  533. X            else
  534. X            {
  535. X                if (*s == '"' && ! (inquotes && insingle))
  536. X                {
  537. X                    inquotes = ! inquotes;
  538. X                    indouble = TRUE;
  539. X                    insingle = FALSE;
  540. X                }
  541. X                or (*s == '\'' && ! (inquotes && indouble))
  542. X                {
  543. X                    inquotes = ! inquotes;
  544. X                    insingle = TRUE;
  545. X                    indouble = FALSE;
  546. X                }
  547. X
  548. X                buf[i++] = *s;
  549. X            }
  550. X        }
  551. X
  552. X        if (i == oldi || buf[i-1] == '\n' || buf[i-1] == '\r' || buf[i-1] == '\f')
  553. X            lastblank = FALSE;
  554. X        else
  555. X        {
  556. X            lastblank = TRUE;
  557. X            buf[i++] = ' ';
  558. X        }
  559. X    }
  560. X
  561. X    buf[i] = '\0';
  562. X    if (i >= MAXSIZE)
  563. X    {
  564. X        fprintf(stderr, "cake internal error: command '%s' too long\n", buf);
  565. X        exit_cake(FALSE);
  566. X    }
  567. X
  568. X    while (buf[i-1] == ' ' || buf[i-1] == '\t')
  569. X        buf[--i] = '\0';
  570. X
  571. X    return new_name(buf);
  572. X}
  573. X
  574. X/*
  575. X**    Clean up after an error or interrupt.
  576. X*/
  577. X
  578. Xcake_error(node)
  579. Xreg    Node    *node;
  580. X{
  581. X    reg    List    *ptr, *ptr1;
  582. X    reg    Node    *bnode, *onode;
  583. X
  584. X    for_list (ptr, node->n_new)
  585. X    {
  586. X        bnode = (Node *) ldata(ptr);
  587. X        for_list (ptr1, bnode->n_old)
  588. X        {
  589. X            onode = (Node *) ldata(ptr1);
  590. X            set_node(onode, nf_NODELETE);
  591. X        }
  592. X
  593. X        if (on_node(bnode, nf_EXIST) && off_node(bnode, nf_PRECIOUS))
  594. X            cake_remove(bnode->n_name);
  595. X    }
  596. X}
  597. X
  598. X/*
  599. X**    Clean up after all the fuss.
  600. X*/
  601. X
  602. Xcleanup()
  603. X{
  604. X    extern    List    *get_allnodes();
  605. X    reg    List    *ptr, *ptr1;
  606. X    reg    List    *nodes;
  607. X    reg    Node    *node, *onode;
  608. X
  609. X    cdebug("cleanup:\n");
  610. X
  611. X    if (nflag)
  612. X        return;
  613. X
  614. X    nodes = get_allnodes();
  615. X    for_list (ptr, nodes)
  616. X    {
  617. X        node = (Node *) ldata(ptr);
  618. X        cdebug("considering %s: ", node->n_name);
  619. X
  620. X        if (off_node(node, nf_EXIST))
  621. X        {
  622. X            cdebug("nonexistent\n");
  623. X            continue;
  624. X        }
  625. X
  626. X        if (on_node(node, nf_ERR) || is_noway(node))
  627. X        {
  628. X            cdebug("errors or noway\n");
  629. X            continue;
  630. X        }
  631. X
  632. X        if (! dflag && off_node(node, nf_REDUNDANT))
  633. X        {
  634. X            cdebug("no flag\n");
  635. X            continue;
  636. X        }
  637. X
  638. X        /* file exists and OK, shall we delete it ? */
  639. X
  640. X        /* not if we thought earlier it need it */
  641. X        if (on_node(node, nf_NODELETE))
  642. X        {
  643. X            cdebug("nodelete flag\n");
  644. X            continue;
  645. X        }
  646. X
  647. X        /* not if it cannot be regenerated at all */
  648. X        if (length(node->n_act) == 0)
  649. X        {
  650. X            cdebug("nonregenerable\n");
  651. X            continue;
  652. X        }
  653. X
  654. X        /* not if it cannot be regenerated as is */
  655. X        if ((node->n_utime < node->n_rtime) && off_node(node, nf_NEWFILE))
  656. X        {
  657. X            cdebug("nonregenerable as is\n");
  658. X            continue;
  659. X        }
  660. X
  661. X        /* or if its ancestors are not all OK */
  662. X        for_list (ptr1, node->n_old)
  663. X        {
  664. X            onode = (Node *) ldata(ptr1);
  665. X            if (! is_ok(onode))
  666. X            {
  667. X                cdebug("ancestor not ok\n");
  668. X                goto nextnode;
  669. X            }
  670. X        }
  671. X
  672. X        cdebug("DELETED\n");
  673. X        cake_remove(node->n_name);
  674. X    
  675. X    nextnode:    ;
  676. X    }
  677. X}
  678. SHAR_EOF
  679. if test 12578 -ne "`wc -c < 'act.c'`"
  680. then
  681.     echo shar: "error transmitting 'act.c'" '(should have been 12578 characters)'
  682. fi
  683. fi
  684. echo shar: "extracting 'chase.c'" '(13609 characters)'
  685. if test -f 'chase.c'
  686. then
  687.     echo shar: "will not over-write existing file 'chase.c'"
  688. else
  689. sed 's/^X//' << \SHAR_EOF > 'chase.c'
  690. X/*
  691. X**    Module to chase Cake dependencies.
  692. X*/
  693. X
  694. Xstatic    char
  695. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/chase.c,v 1.14 86/07/19 12:22:39 zs Exp $";
  696. X
  697. X#include    "cake.h"
  698. X
  699. X/*
  700. X**    The main chasing function. It checks all entries to see
  701. X**    if they describe a dependency of the name. If the second arg
  702. X**    is not NULL, it is taken as a fixed choice (by another do_chase)
  703. X**    as to which entry will actually be used to generate the name.
  704. X**
  705. X**    The kinds of nodes returned by do_chase are as follows.
  706. X**    OK means that no action is needed to update the name.
  707. X**    CANDO means that the action is known and there is no reason
  708. X**    why it shouldn't succeed. NOWAY is set when neither of those
  709. X**    conditions is satisfied. nf_ERR means that some error has
  710. X**    occurred; nf_ERR nodes are never touched again; except for
  711. X**    printing the error messages themselves. (NOWAY nodes *are*
  712. X**    touched by act.c to update as many ancestors as possible.)
  713. X**
  714. X**    Whenever nf_ERR is not set, do_chase sets the utime field,
  715. X**    and the rtime field as well if the file exists.
  716. X*/
  717. X
  718. Xdo_chase(node, picked)
  719. Xreg    Node    *node;
  720. Xreg    Entry    *picked;
  721. X{
  722. X    extern        get_utime();
  723. X    extern    time_t    cake_gettime();
  724. X    extern    Node    *chase();
  725. X    extern    Node    *chase_node();
  726. X    extern    time_t    pick_time();
  727. X    extern    bool    match();
  728. X    extern    bool    eval();
  729. X    extern    Entry    *ground_entry();
  730. X    extern    Test    *deref_test();
  731. X    extern        deref_entry();
  732. X    extern    List    *entries;
  733. X    extern    char    *list_names();
  734. X    Env        env;
  735. X    reg    List    *ptr, *ptr1, *ptr2;
  736. X    reg    Node    *newnode, *onode;
  737. X    reg    Entry    *entry, *newentry;
  738. X    reg    Pat    *pat;
  739. X    reg    List    *entry_anay, *entry_ayea;    /* of Entry    */
  740. X    reg    List    *miss_anay, *miss_ayea;        /* of Node    */
  741. X    reg    List    *pot_entry;        /* of Entry    */
  742. X    reg    List    *pot_pat;        /* of Pat    */
  743. X    reg    List    *probe_old;        /* of Node    */
  744. X    reg    bool    found, missing;
  745. X    reg    bool    singleton, orphan;
  746. X
  747. X    put_trail("do_chase", "start");
  748. X    cdebug("chasing %s\n", node->n_name);
  749. X
  750. X    if (off_node(node, nf_EXIST))
  751. X        set_node(node, nf_NEWFILE);
  752. X
  753. X    /* find all entries which could generate this name */
  754. X    pot_entry = makelist0();
  755. X    pot_pat   = makelist0();
  756. X    for_list (ptr, entries)
  757. X    {
  758. X        entry = (Entry *) ldata(ptr);
  759. X        /* try everything on the left side of the entry */
  760. X        for_list (ptr1, entry->e_new)
  761. X        {
  762. X            pat = (Pat *) ldata(ptr1);
  763. X            if (match(env, node->n_name, pat))
  764. X            {
  765. X                if ((newentry = ground_entry(env, entry)) == (Entry *) NULL)
  766. X                {
  767. X                    sprintf(scratchbuf, "cannot perform substitutions on entry for %s",
  768. X                        node->n_name);
  769. X                    add_error(node, new_name(scratchbuf), LNULL, TRUE);
  770. X                    goto end;
  771. X                }
  772. X
  773. X#ifdef    CAKEDEBUG
  774. X                if (entrydebug)
  775. X                {
  776. X                    printf("Applicable entry\n");
  777. X                    print_entry(newentry);
  778. X                }
  779. X#endif
  780. X
  781. X                addtail(pot_entry, newentry);    /* na */
  782. X                addtail(pot_pat, pat);        /* na */
  783. X                break;
  784. X            }
  785. X        }
  786. X    }
  787. X
  788. X    cdebug("%s: %d potentials\n", node->n_name, length(pot_entry));
  789. X
  790. X    /* find out which tests are satisfied */
  791. X    entry_anay = makelist0();
  792. X    entry_ayea = makelist0();
  793. X    for_2list (ptr1, ptr2, pot_entry, pot_pat)
  794. X    {
  795. X        entry = (Entry *) ldata(ptr1);
  796. X        pat = (Pat *) ldata(ptr2);
  797. X
  798. X        for_list (ptr, entry->e_when)
  799. X        {
  800. X            reg    Node    *whennode;
  801. X            reg    Pat    *whenpat;
  802. X
  803. X            whenpat  = (Pat *) ldata(ptr);
  804. X            whennode = chase(whenpat->p_str, whenpat->p_flag, (Entry *) NULL);
  805. X            if (off_node(whennode, nf_ERR))
  806. X            {
  807. X                if (is_ok(whennode))
  808. X                    continue;
  809. X
  810. X                if (nflag && off_node(whennode, nf_WARNED))
  811. X                {
  812. X                    printf("cake -n: warning, need to make %s to find dependencies\n",
  813. X                        whenpat->p_str);
  814. X                    set_node(whennode, nf_WARNED);
  815. X                }
  816. X
  817. X                update(whennode, 100, TRUE);
  818. X            }
  819. X
  820. X            if (on_node(whennode, nf_ERR) || ! is_ok(whennode))
  821. X            {
  822. X                sprintf(scratchbuf, "cannot find out if entry applies to %s",
  823. X                    node->n_name);
  824. X                add_error(node, new_name(scratchbuf), makelist(whennode), TRUE);
  825. X                return;
  826. X            }
  827. X        }
  828. X
  829. X#ifdef    CAKEDEBUG
  830. X        if (entrydebug)
  831. X        {
  832. X            printf("about to test condition\n");
  833. X            print_entry(entry);
  834. X        }
  835. X#endif
  836. X
  837. X        entry->e_cond = deref_test(entry->e_cond);
  838. X        if (! eval(node, entry->e_cond, env))
  839. X        {
  840. X            cdebug("condition FALSE\n");
  841. X            continue;
  842. X        }
  843. X
  844. X        /* here we know that this entry applies */
  845. X        deref_entry(env, entry);
  846. X
  847. X        if (Lflag)
  848. X        {
  849. X            for_list (ptr, entry->e_old)
  850. X            {
  851. X                reg    Pat    *opat;
  852. X
  853. X                opat = (Pat *) ldata(ptr);
  854. X                if (streq(node->n_name, opat->p_str))
  855. X                {
  856. X                    cdebug("found loop in entry at %s\n", node->n_name);
  857. X                    continue;
  858. X                }
  859. X            }
  860. X        }
  861. X
  862. X        node->n_flag |= pat->p_flag;
  863. X        if (length(entry->e_act) == 0)
  864. X            addtail(entry_anay, entry);    /* no assigment */
  865. X        else
  866. X            addtail(entry_ayea, entry);    /* no assigment */
  867. X    }
  868. X
  869. X    if (on_node(node, nf_ERR))
  870. X        return;
  871. X
  872. X    cdebug("%s: no action: %d, with actions: %d\n",
  873. X        node->n_name, length(entry_anay), length(entry_ayea));
  874. X
  875. X    /* All entries considered from now on are ground */
  876. X
  877. X    /* see if the file is an original */
  878. X    if (length(entry_anay) == 0 && length(entry_ayea) == 0)
  879. X    {
  880. X        if (off_node(node, nf_EXIST))
  881. X        {
  882. X            cdebug("%s: noway\n", node->n_name);
  883. X            node->n_kind  = n_NOWAY;
  884. X            node->n_utime = GENESIS;
  885. X            sprintf(scratchbuf, "base file %s does not exist", node->n_name);
  886. X            add_error(node, new_name(scratchbuf), LNULL, FALSE);
  887. X            goto end;
  888. X        }
  889. X
  890. X        set_node(node, nf_ORIG);
  891. X        cdebug("%s: orig ok\n", node->n_name);
  892. X        node->n_kind  = n_OK;
  893. X        node->n_utime = node->n_rtime;
  894. X        goto end;
  895. X    }
  896. X
  897. X    /* see to actionless dependencies */
  898. X    missing = FALSE;
  899. X    miss_anay = NULL;
  900. X    for_list (ptr, entry_anay)
  901. X    {
  902. X        entry = (Entry *) ldata(ptr);
  903. X        for_list (ptr1, entry->e_old)
  904. X        {
  905. X            pat = (Pat *) ldata(ptr1);
  906. X            newnode = chase(pat->p_str, pat->p_flag, (Entry *) NULL);
  907. X            if (on_node(newnode, nf_ERR) || is_noway(newnode))
  908. X            {
  909. X                missing = TRUE;
  910. X                miss_anay = addtail(miss_anay, newnode);
  911. X            }
  912. X
  913. X            addtail(node->n_old, newnode);    /* na */
  914. X        }
  915. X    }
  916. X
  917. X    cdebug("%s: unconditional dependencies, %s\n",
  918. X        node->n_name, missing? "some missing": "all there");
  919. X
  920. X    /*
  921. X    **    If necessary, choose a feasible action dependency.
  922. X    **    However, if there is only one, select it even if
  923. X    **    it is not feasible.
  924. X    */
  925. X
  926. X    found = FALSE;
  927. X    miss_ayea = NULL;
  928. X    if (picked == (Entry *) NULL)
  929. X    {
  930. X        singleton = (length(entry_ayea) == 1);
  931. X        orphan    = (length(entry_ayea) == 0);
  932. X
  933. X        for_list (ptr, entry_ayea)
  934. X        {
  935. X            entry = (Entry *) ldata(ptr);
  936. X            /* first copy of this code, with chase */
  937. X            found = TRUE; /* assume it for the moment */
  938. X            probe_old = makelist0();
  939. X            for_list (ptr1, entry->e_old)
  940. X            {
  941. X                pat = (Pat *) ldata(ptr1);
  942. X                newnode = chase(pat->p_str, pat->p_flag, (Entry *) NULL);
  943. X                if (on_node(newnode, nf_ERR) || is_noway(newnode))
  944. X                {
  945. X                    found = FALSE;
  946. X                    miss_ayea = addtail(miss_ayea, newnode);
  947. X                    if (! singleton)
  948. X                        break;
  949. X                }
  950. X
  951. X                addtail(probe_old, newnode);    /* na */
  952. X            }
  953. X
  954. X            if (found)
  955. X                break;
  956. X        }
  957. X    }
  958. X    else
  959. X    {
  960. X        singleton = TRUE;
  961. X        orphan    = FALSE;
  962. X
  963. X        cdebug("%s: was given generator\n", node->n_name);
  964. X        entry = picked;
  965. X
  966. X        /* second copy of this code, with chase_node */
  967. X        found = TRUE; /* assume it for the moment */
  968. X        probe_old = makelist0();
  969. X        for_list (ptr1, entry->e_old)
  970. X        {
  971. X            pat = (Pat *) ldata(ptr1);
  972. X            newnode = chase_node(pat->p_str);
  973. X            if (on_node(newnode, nf_ERR) || is_noway(newnode))
  974. X            {
  975. X                found = FALSE;
  976. X                miss_ayea = addtail(miss_ayea, newnode);
  977. X                if (! singleton)
  978. X                    break;
  979. X            }
  980. X
  981. X            addtail(probe_old, newnode);    /* na */
  982. X        }
  983. X    }
  984. X
  985. X    if (found)
  986. X    {
  987. X        /* we have found an applicable entry */
  988. X        cdebug("%s: found feasible generator\n", node->n_name);
  989. X        addlist(node->n_old, probe_old);    /* na */
  990. X        node->n_act = entry->e_act;
  991. X        if (picked == (Entry *) NULL)
  992. X            set_buddies(node, entry);
  993. X        picked = entry;
  994. X    }
  995. X    or (singleton)
  996. X    {
  997. X        /* we have only one (inapplicable) entry */
  998. X        /* so we shall make do as best we can */
  999. X        cdebug("%s: found single infeasible generator\n", node->n_name);
  1000. X        addlist(node->n_old, probe_old);    /* na */
  1001. X        node->n_act = entry->e_act;
  1002. X        if (picked == (Entry *) NULL)
  1003. X            set_buddies(node, entry);
  1004. X        picked = entry;
  1005. X    }
  1006. X    or (orphan && on_node(node, nf_PSEUDO))
  1007. X    {
  1008. X        /* no entry is needed, act as we had one */
  1009. X        found = TRUE;
  1010. X        cdebug("%s: no generator, no problem\n", node->n_name);
  1011. X        node->n_act = makelist0();
  1012. X    }
  1013. X    else
  1014. X    {
  1015. X        cdebug("%s: no feasible generator\n", node->n_name);
  1016. X        node->n_act = makelist0();
  1017. X    }
  1018. X
  1019. X    if (length(node->n_act) > 0 && length(picked->e_old) == 0)
  1020. X        node->n_utime = cake_gettime();
  1021. X    else
  1022. X        get_utime(node, TRUE);
  1023. X
  1024. X    for_list (ptr, node->n_old)
  1025. X    {
  1026. X        newnode = (Node *) ldata(ptr);
  1027. X        if (on_node(newnode, nf_NONVOL))
  1028. X            set_node(node, nf_DEPNONVOL);
  1029. X    }
  1030. X
  1031. X    if (missing)
  1032. X    {
  1033. X        node->n_kind = n_NOWAY;
  1034. X        sprintf(scratchbuf, "%s is missing the prerequisite%s %s",
  1035. X            node->n_name, length(miss_anay)==1? "": "s", list_names(miss_anay));
  1036. X        add_error(node, new_name(scratchbuf), miss_anay, FALSE);
  1037. X    }
  1038. X    or (! found)
  1039. X    {
  1040. X        node->n_kind = n_NOWAY;
  1041. X        if (miss_ayea == (List *) NULL)
  1042. X            sprintf(scratchbuf, "%s has no applicable entries with actions\n",
  1043. X                node->n_name);
  1044. X        else
  1045. X            sprintf(scratchbuf, "%s is missing the ancestor%s %s",
  1046. X                node->n_name, length(miss_ayea)==1? "": "s", list_names(miss_ayea));
  1047. X
  1048. X        add_error(node, new_name(scratchbuf), miss_ayea, FALSE);
  1049. X    }
  1050. X    or (on_node(node, nf_EXIST) && node->n_utime <= node->n_rtime)
  1051. X        node->n_kind = n_OK;
  1052. X    or (on_node(node, nf_PSEUDO) && length(node->n_act) == 0)
  1053. X    {
  1054. X        node->n_kind = n_OK;
  1055. X        for_list (ptr, node->n_old)
  1056. X        {
  1057. X            onode = (Node *) ldata(ptr);
  1058. X            if (is_cando(onode))
  1059. X                node->n_kind = n_CANDO;
  1060. X        }
  1061. X    }
  1062. X    else
  1063. X        node->n_kind = n_CANDO;
  1064. X    
  1065. Xend:
  1066. X#ifdef    CAKEDEBUG
  1067. X    if (cakedebug)
  1068. X    {
  1069. X        printf("chase exit\n");
  1070. X        print_node(node);
  1071. X    }
  1072. X#endif
  1073. X
  1074. X    put_trail("do_chase", "finish");
  1075. X}
  1076. X
  1077. X/*
  1078. X**    Calculate the "update time" of the given node. The second arg
  1079. X**    tells us whether we should set a flag for nonvolatile ancestors.
  1080. X*/
  1081. X
  1082. Xget_utime(node, planning)
  1083. Xreg    Node    *node;
  1084. Xreg    bool    planning;
  1085. X{
  1086. X    extern    time_t    get_youngest(), cake_gettime();
  1087. X    reg    time_t    youngest;
  1088. X
  1089. X    if ((youngest = get_youngest(node, planning)) == GENESIS)
  1090. X        node->n_utime = cake_gettime();
  1091. X    else
  1092. X        node->n_utime = youngest;
  1093. X}
  1094. X
  1095. X/*
  1096. X**    Return the time of update of the youngest dependent.
  1097. X*/
  1098. X
  1099. Xtime_t
  1100. Xget_youngest(node, planning)
  1101. Xreg    Node    *node;
  1102. Xreg    bool    planning;
  1103. X{
  1104. X    reg    List    *ptr;
  1105. X    reg    Node    *onode;
  1106. X    reg    time_t    youngest, picked_time;
  1107. X    reg    List    *errnodes;
  1108. X
  1109. X    youngest = GENESIS;
  1110. X    errnodes = NULL;
  1111. X    for_list (ptr, node->n_old)
  1112. X    {
  1113. X        onode = (Node *) ldata(ptr);
  1114. X        if (on_node(onode, nf_ERR))
  1115. X            errnodes = addtail(errnodes, onode);
  1116. X        else
  1117. X        {
  1118. X            if ((picked_time = pick_time(onode, planning)) > youngest)
  1119. X                youngest = picked_time;
  1120. X        }
  1121. X    }
  1122. X
  1123. X    if (errnodes != (List *) NULL)
  1124. X    {
  1125. X        sprintf(scratchbuf, "don't know what to do with %s because of problems with %s",
  1126. X            node->n_name, list_names(errnodes));
  1127. X        add_error(node, new_name(scratchbuf), errnodes, TRUE);
  1128. X    }
  1129. X
  1130. X    return youngest;
  1131. X}
  1132. X
  1133. X/*
  1134. X**    Take care of the names mentioned alongside node's
  1135. X**    on the left hand side of the given ground entry.
  1136. X**
  1137. X**    If a node exists for one of these names we know that
  1138. X**    a producer must have been chosen for it, and we know that
  1139. X**    it is not this rule (if it were, then the caller would not
  1140. X**    have done anything about buddies). This is an inconsistency.
  1141. X*/
  1142. X
  1143. Xset_buddies(node, entry)
  1144. Xreg    Node    *node;
  1145. Xreg    Entry    *entry;
  1146. X{
  1147. X    extern    Node    *chase_node();
  1148. X    reg    List    *list;
  1149. X    reg    List    *ptr;
  1150. X    reg    Node    *newnode;
  1151. X    reg    Pat    *pat;
  1152. X    reg    List    *errnodes;
  1153. X
  1154. X    put_trail("set_buddies", "start");
  1155. X    list = makelist(node);
  1156. X    errnodes = NULL;
  1157. X    for_list (ptr, entry->e_new)
  1158. X    {
  1159. X        pat = (Pat *) ldata(ptr);
  1160. X        if (streq(pat->p_str, node->n_name))
  1161. X            continue;
  1162. X        
  1163. X        if ((newnode = chase_node(pat->p_str)) != (Node *) NULL)
  1164. X            errnodes = addtail(errnodes, newnode);
  1165. X        else
  1166. X        {
  1167. X            newnode = chase(pat->p_str, pat->p_flag, entry);
  1168. X            addtail(list, newnode);    /* no assigment */
  1169. X        }
  1170. X    }
  1171. X
  1172. X    for_list (ptr, list)
  1173. X    {
  1174. X        newnode = (Node *) ldata(ptr);
  1175. X        newnode->n_new = list;
  1176. X
  1177. X        if (errnodes != (List *) NULL)
  1178. X        {
  1179. X            sprintf(scratchbuf, "cannot update %s because of interference with %s %s",
  1180. X                newnode->n_name, (length(errnodes) == 1)? "buddy": "buddies",
  1181. X                list_names(errnodes));
  1182. X            add_error(node, new_name(scratchbuf), errnodes, TRUE);
  1183. X        }
  1184. X    }
  1185. X
  1186. X    put_trail("set_buddies", "finish");
  1187. X}
  1188. X
  1189. X/*
  1190. X**    Pick the appropriate time to use in decisions
  1191. X**    about dependencies. The algorithms differ in the
  1192. X**    twp phases: in the execution phase real times
  1193. X**    override any calculated times.
  1194. X*/
  1195. X
  1196. Xtime_t
  1197. Xpick_time(node, planning)
  1198. Xreg    Node    *node;
  1199. Xreg    bool    planning;
  1200. X{
  1201. X    if (off_node(node, nf_EXIST))
  1202. X        return node->n_utime;
  1203. X    
  1204. X    if (planning)
  1205. X        return max(node->n_rtime, node->n_utime);
  1206. X
  1207. X    return node->n_rtime;
  1208. X}
  1209. X
  1210. X/*
  1211. X**    Chase down the ancestors of the given name.
  1212. X**    Return the node describing the dependency graph.
  1213. X**
  1214. X**    Note that this is merely an interface function,
  1215. X**    serving to cache previous results and to detect cycles.
  1216. X*/
  1217. X
  1218. Xchar    *goal_stack[MAXGSTACK];
  1219. Xint    goal_stackp = 0;
  1220. X
  1221. XNode *
  1222. Xchase(name, flag, picked)
  1223. Xreg    char    *name;
  1224. Xreg    bool    flag;
  1225. Xreg    Entry    *picked;
  1226. X{
  1227. X    extern    Table    node_tab;
  1228. X    extern        do_chase();
  1229. X    extern    char    *find_circle();
  1230. X    reg    Node    *node;
  1231. X
  1232. X    if ((node = (Node *) lookup_table(node_tab, name)) == NULL)
  1233. X    {
  1234. X        node = make_node(name);
  1235. X        if (goal_stackp >= MAXGSTACK)
  1236. X        {
  1237. X            printf("cake: dependency nesting level %d too deep\n", goal_stackp);
  1238. X            exit_cake(FALSE);
  1239. X        }
  1240. X
  1241. X        goal_stack[goal_stackp++] = name;
  1242. X#ifdef    CAKEDEBUG
  1243. X        cdebug("stack[%d] = %s\n", goal_stackp-1, goal_stack[goal_stackp-1]);
  1244. X#endif
  1245. X        set_node(node, nf_BUSY);
  1246. X        insert_table(node_tab, node);
  1247. X        do_chase(node, picked);
  1248. X        --goal_stackp;
  1249. X        reset_node(node, nf_BUSY);
  1250. X    }
  1251. X    else
  1252. X    {
  1253. X        cdebug("Using cache for %s\n", name);
  1254. X        if (on_node(node, nf_BUSY))
  1255. X        {
  1256. X            node->n_flag |= flag;
  1257. X            sprintf(scratchbuf, "%s depends upon itself %s", node->n_name,
  1258. X                find_circle(node->n_name));
  1259. X            add_error(node, new_name(scratchbuf), LNULL, TRUE);
  1260. X            put_trail("chase", "finish");
  1261. X            return node;
  1262. X        }
  1263. X    }
  1264. X
  1265. X    node->n_flag |= flag;
  1266. X    put_trail("chase", "finish");
  1267. X    return node;
  1268. X}
  1269. SHAR_EOF
  1270. if test 13609 -ne "`wc -c < 'chase.c'`"
  1271. then
  1272.     echo shar: "error transmitting 'chase.c'" '(should have been 13609 characters)'
  1273. fi
  1274. fi
  1275. echo shar: "extracting 'entry.c'" '(11376 characters)'
  1276. if test -f 'entry.c'
  1277. then
  1278.     echo shar: "will not over-write existing file 'entry.c'"
  1279. else
  1280. sed 's/^X//' << \SHAR_EOF > 'entry.c'
  1281. X/*
  1282. X**    Module to record and process Cake dependency entries.
  1283. X*/
  1284. X
  1285. Xstatic    char
  1286. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/entry.c,v 1.14 86/07/19 12:22:52 zs Exp $";
  1287. X
  1288. X#include    "cake.h"
  1289. X#include    <ctype.h>
  1290. X
  1291. XList    *entries;
  1292. XEntry    *main_entry;
  1293. X
  1294. Xextern    Test    *ground_test();
  1295. X
  1296. X#define    ground_pat(env, pat)    make_pat(ground(env, pat->p_str), pat->p_cmd, pat->p_flag);
  1297. X#define    ground_act(env, act)    make_act(ground(env, act->a_str), act->a_flag);
  1298. X
  1299. X/*
  1300. X**    Initialise ALL data structures about entries.
  1301. X*/
  1302. X
  1303. Xinit_entry()
  1304. X{
  1305. X    entries = makelist0();
  1306. X    main_entry = (Entry *) NULL;
  1307. X}
  1308. X
  1309. X/*
  1310. X**    Deposit an entry just read in.
  1311. X*/
  1312. X
  1313. Xnew_entry(deps, acts)
  1314. Xreg    List    *deps;                /* of Entry    */
  1315. Xreg    List    *acts;                /* of Pat    */
  1316. X{
  1317. X    reg    List    *ptr;
  1318. X    reg    Entry    *entry;
  1319. X
  1320. X    for_list (ptr, deps)
  1321. X    {
  1322. X        entry = (Entry *) ldata(ptr);
  1323. X        entry->e_act  = acts;
  1324. X        addtail(entries, entry);    /* no assignment */
  1325. X    }
  1326. X}
  1327. X
  1328. X/*
  1329. X**    Prepare entries for matches against their left hand sides.
  1330. X**    This essentially means dereferencing any command patterns.
  1331. X**    Another minor correction is also done here: if -n is given
  1332. X**    then we set nf_PRECIOUS so no file is deleted.
  1333. X*/
  1334. X
  1335. Xprep_entries()
  1336. X{
  1337. X    extern    List    *break_pat();
  1338. X    reg    List    *ptr, *ptr1;
  1339. X    reg    Entry    *entry;
  1340. X    reg    Pat    *pat;
  1341. X    reg    List    *newnew;
  1342. X
  1343. X    for_list (ptr, entries)
  1344. X    {
  1345. X        entry = (Entry *) ldata(ptr);
  1346. X
  1347. X        newnew = makelist0();
  1348. X        for_list (ptr1, entry->e_new)
  1349. X        {
  1350. X            pat = (Pat *) ldata(ptr1);
  1351. X            if (on_pat(pat, nf_WHEN))
  1352. X            {
  1353. X                printf("cake: inappropriate flag '*' after target %s ignored\n",
  1354. X                    pat->p_str);
  1355. X                reset_pat(pat, nf_WHEN);
  1356. X            }
  1357. X
  1358. X            if (nflag)
  1359. X                set_pat(pat, nf_PRECIOUS);
  1360. X
  1361. X            if (! pat->p_cmd)
  1362. X                addtail(newnew, pat);        /* na */
  1363. X            else
  1364. X            {
  1365. X                deref(pat, TRUE);
  1366. X                addlist(newnew, break_pat(pat));/* na */
  1367. X            }
  1368. X        }
  1369. X
  1370. X        entry->e_new = newnew;
  1371. X
  1372. X        for_list (ptr1, entry->e_old)
  1373. X        {
  1374. X            pat = (Pat *) ldata(ptr1);
  1375. X            if (pat->p_cmd && on_pat(pat, nf_WHEN))
  1376. X            {
  1377. X                printf("cake: inappropriate flag '*' after command source %s ignored\n",
  1378. X                    pat->p_str);
  1379. X                reset_pat(pat, nf_WHEN);
  1380. X            }
  1381. X        }
  1382. X
  1383. X#ifdef    CAKEDEBUG
  1384. X        if (entrydebug)
  1385. X        {
  1386. X            printf("prepared entry:\n");
  1387. X            print_entry(entry);
  1388. X        }
  1389. X#endif
  1390. X    }
  1391. X}
  1392. X
  1393. X/*
  1394. X**    Enter the last (main) entry. This entry has a distinguished
  1395. X**    left hand side consisting of the sole pattern CHASEROOT.
  1396. X**    This is the pattern which cake tries to make up-to-date.
  1397. X**    If there were nonoption arguments on the command line,
  1398. X**    CHASEROOT is made to depend on them; otherwise the left hand
  1399. X**    side of the first concrete entry is used, as in make.
  1400. X**    However, if the first concrete entry is in an included file,
  1401. X**    we keep looking, unless it had a double colon.
  1402. X*/
  1403. X
  1404. Xfinal_entry(argc, argv)
  1405. Xreg    int    argc;
  1406. Xreg    char    *argv[];
  1407. X{
  1408. X    extern    bool    hasvars();
  1409. X    reg    List    *ptr, *ptr1;
  1410. X    reg    Entry    *entry, *foundentry;
  1411. X    reg    Pat    *pat;
  1412. X    reg    bool    found_main, found_incl;
  1413. X    reg    int    i;
  1414. X
  1415. X    main_entry = make(Entry);
  1416. X    main_entry->e_new  = makelist(make_pat(CHASEROOT, FALSE, nf_PSEUDO|nf_NODELETE));
  1417. X    main_entry->e_old  = makelist0();
  1418. X    main_entry->e_cond = (Test *) NULL;
  1419. X    main_entry->e_act  = makelist0();
  1420. X
  1421. X    cdebug("target count %d\n", argc-1);
  1422. X
  1423. X    if (argc > 1)
  1424. X    {
  1425. X        for (i = 1; i < argc; i++)
  1426. X        {
  1427. X            cdebug("target %s\n", argv[i]);
  1428. X            addtail(main_entry->e_old, make_pat(argv[i], FALSE, 0));    /* na */
  1429. X        }
  1430. X    }
  1431. X    else
  1432. X    {
  1433. X        /* find the first entry without variables */
  1434. X        found_main = FALSE;
  1435. X        found_incl = FALSE;
  1436. X        for_list (ptr, entries)
  1437. X        {
  1438. X            entry = (Entry *) ldata(ptr);
  1439. X            for_list (ptr1, entry->e_new)
  1440. X            {
  1441. X                pat = (Pat *) ldata(ptr1);
  1442. X                if (hasvars(pat->p_str))
  1443. X                    goto nextentry;
  1444. X            }
  1445. X
  1446. X            if (streq(entry->e_file, cakefile) || entry->e_dblc)
  1447. X            {
  1448. X                found_main = TRUE;
  1449. X                foundentry = entry;
  1450. X                break;
  1451. X            }
  1452. X            or (! found_incl)
  1453. X            {
  1454. X                found_incl = TRUE;
  1455. X                foundentry = entry;
  1456. X            }
  1457. X
  1458. X        nextentry:    ;
  1459. X        }
  1460. X
  1461. X        if (! found_main && ! found_incl)
  1462. X        {
  1463. X            printf("cake: no entries without variables\n");
  1464. X            printf("cake: don't know what cake to bake\n");
  1465. X            exit(1);
  1466. X        }
  1467. X
  1468. X        /* update everything on its left side */
  1469. X        for_list (ptr, foundentry->e_new)
  1470. X        {
  1471. X            pat = (Pat *) ldata(ptr);
  1472. X            addtail(main_entry->e_old, pat);    /* na */
  1473. X        }
  1474. X    }
  1475. X
  1476. X    addtail(entries, main_entry);    /* no assigment */
  1477. X}
  1478. X
  1479. X
  1480. X/*
  1481. X**    Return a new entry which is a ground version of the one passed.
  1482. X**    Process '*' flags and set up e_when accordingly.
  1483. X*/
  1484. X
  1485. XEntry *
  1486. Xground_entry(env, entry)
  1487. XEnv        env;
  1488. Xreg    Entry    *entry;
  1489. X{
  1490. X    extern        do_when();
  1491. X    extern    List    *break_pat();
  1492. X    extern    char    *ground();
  1493. X    reg    List    *ptr;
  1494. X    reg    Entry    *newentry;
  1495. X    reg    Pat    *pat, *newpat;
  1496. X    reg    Act    *act, *newact;
  1497. X
  1498. X    put_trail("ground_entry", "start");
  1499. X    newentry = make(Entry);
  1500. X    newentry->e_new  = makelist0();
  1501. X    newentry->e_old  = makelist0();
  1502. X    newentry->e_act  = makelist0();
  1503. X    newentry->e_when = makelist0();
  1504. X
  1505. X    for_list (ptr, entry->e_new)
  1506. X    {
  1507. X        /* prep_entries made these patterns command free */
  1508. X        pat = (Pat *) ldata(ptr);
  1509. X        newpat = ground_pat(env, pat);
  1510. X        do_when(newentry, newpat);
  1511. X        addtail(newentry->e_new, newpat);    /* na */
  1512. X    }
  1513. X
  1514. X    for_list (ptr, entry->e_old)
  1515. X    {
  1516. X        pat = (Pat *) ldata(ptr);
  1517. X        newpat = ground_pat(env, pat);
  1518. X        do_when(newentry, newpat);
  1519. X        addtail(newentry->e_old, newpat);    /* na */
  1520. X    }
  1521. X
  1522. X    for_list (ptr, entry->e_act)
  1523. X    {
  1524. X        act = (Act *) ldata(ptr);
  1525. X        newact = ground_act(env, act);
  1526. X        addtail(newentry->e_act, newact);    /* na */
  1527. X    }
  1528. X
  1529. X    newentry->e_cond = ground_test(env, entry->e_cond);
  1530. X
  1531. X    put_trail("ground_entry", "finish");
  1532. X    return newentry;
  1533. X}
  1534. X
  1535. X/*
  1536. X**    Look after '*' (when) flags.
  1537. X*/
  1538. X
  1539. Xdo_when(entry, pat)
  1540. Xreg    Entry    *entry;
  1541. Xreg    Pat    *pat;
  1542. X{
  1543. X    if (on_pat(pat, nf_WHEN))
  1544. X    {
  1545. X        reset_pat(pat, nf_WHEN);
  1546. X        entry->e_when = addtail(entry->e_when, pat);
  1547. X    }
  1548. X}
  1549. X
  1550. X/*
  1551. X**    Ground a test.
  1552. X*/
  1553. X
  1554. XTest *
  1555. Xground_test(env, test)
  1556. XEnv        env;
  1557. Xreg    Test    *test;
  1558. X{
  1559. X    extern    char    *ground();
  1560. X    reg    List    *ptr;
  1561. X    reg    Pat    *pat, *newpat;
  1562. X    reg    Test    *newtest;
  1563. X
  1564. X    if (test == (Test *) NULL)
  1565. X        return test;
  1566. X
  1567. X    put_trail("ground_test", "start");
  1568. X    switch (test->t_kind)
  1569. X    {
  1570. X
  1571. Xwhen t_TRUE:
  1572. Xcase t_FALSE:    put_trail("ground_test", "finish");
  1573. X        return test;
  1574. X
  1575. Xwhen t_AND:
  1576. Xcase t_OR:    put_trail("ground_test", "finish");
  1577. X        return make_test_b(test->t_kind,
  1578. X            ground_test(env, test->t_left), ground_test(env, test->t_right));
  1579. X
  1580. Xwhen t_NOT:    put_trail("ground_test", "finish");
  1581. X        return make_test_u(test->t_kind, ground_test(env, test->t_left));
  1582. X
  1583. Xwhen t_CMD:    put_trail("ground_test", "finish");
  1584. X        return make_test_c(ground(env, test->t_cmd));
  1585. X
  1586. Xwhen t_MATCH:    pat = ground_pat(env, test->t_pat);
  1587. X        newtest = make_test_mm(pat);
  1588. X        for_list (ptr, test->t_list)
  1589. X        {
  1590. X            pat = (Pat *) ldata(ptr);
  1591. X            newpat = ground_pat(env, pat);
  1592. X            addtail(newtest->t_list, newpat);    /* na */
  1593. X        }
  1594. X
  1595. X        put_trail("ground_test", "finish");
  1596. X        return newtest;
  1597. X
  1598. Xwhen t_LIST:    pat = ground_pat(env, test->t_pat);
  1599. X        newtest = make_test_l(pat, makelist0());
  1600. X        for_list (ptr, test->t_list)
  1601. X        {
  1602. X            pat = (Pat *) ldata(ptr);
  1603. X            newpat = ground_pat(env, pat);
  1604. X            addtail(newtest->t_list, newpat);    /* na */
  1605. X        }
  1606. X
  1607. X        put_trail("ground_test", "finish");
  1608. X        return newtest;
  1609. X
  1610. Xwhen t_EXIST:    newpat = ground_pat(env, test->t_pat);
  1611. X        put_trail("ground_test", "finish");
  1612. X        return make_test_s(t_EXIST, newpat);
  1613. X
  1614. Xwhen t_CANDO:    newpat = ground_pat(env, test->t_pat);
  1615. X        put_trail("ground_test", "finish");
  1616. X        return make_test_s(t_CANDO, newpat);
  1617. X
  1618. Xwhen t_OK:    newpat = ground_pat(env, test->t_pat);
  1619. X        put_trail("ground_test", "finish");
  1620. X        return make_test_s(t_OK, newpat);
  1621. X
  1622. Xotherwise:    printf("cake internal error: bad test type %x in ground_test\n", test->t_kind);
  1623. X        put_trail("ground_test", "finish");
  1624. X        return (Test *) NULL;
  1625. X    }
  1626. X
  1627. X    put_trail("ground_test", "finish");
  1628. X    return (Test *) NULL;
  1629. X}
  1630. X
  1631. X/*
  1632. X**    Dereference all command patterns in the given entry.
  1633. X*/
  1634. X
  1635. Xderef_entry(env, entry)
  1636. XEnv        env;
  1637. Xreg    Entry    *entry;
  1638. X{
  1639. X    reg    List    *ptr, *ptr1;
  1640. X    reg    List    *newlist;
  1641. X    reg    List    *patlist;
  1642. X    reg    Pat    *pat, *oldpat, *newpat;
  1643. X
  1644. X    newlist = makelist0();
  1645. X    for_list (ptr, entry->e_old)
  1646. X    {
  1647. X        pat = (Pat *) ldata(ptr);
  1648. X        if (! pat->p_cmd)
  1649. X            addtail(newlist, pat);    /* na */
  1650. X        else
  1651. X        {
  1652. X            deref(pat, TRUE);
  1653. X            patlist = break_pat(pat);
  1654. X            for_list (ptr1, patlist)
  1655. X            {
  1656. X                oldpat = (Pat *) ldata(ptr1);
  1657. X                newpat = make_pat(ground(env, oldpat->p_str), FALSE, 0);
  1658. X                do_when(entry, newpat);
  1659. X                addtail(newlist, newpat);    /* na */
  1660. X            }
  1661. X        }
  1662. X    }
  1663. X
  1664. X    entry->e_old  = newlist;
  1665. X}
  1666. X
  1667. X/*
  1668. X**    Dereference a test.
  1669. X*/
  1670. X
  1671. XTest *
  1672. Xderef_test(test)
  1673. Xreg    Test    *test;
  1674. X{
  1675. X    extern    char    *expand_cmds();
  1676. X    reg    List    *ptr;
  1677. X    reg    List    *newlist;
  1678. X    reg    Pat    *pat;
  1679. X
  1680. X    if (test == (Test *) NULL)
  1681. X        return test;
  1682. X
  1683. X    put_trail("deref_test", "start");
  1684. X    switch (test->t_kind)
  1685. X    {
  1686. X
  1687. Xwhen t_TRUE:
  1688. Xcase t_FALSE:    put_trail("deref_test", "finish");
  1689. X        return test;
  1690. X
  1691. Xwhen t_AND:
  1692. Xcase t_OR:    test->t_left  = deref_test(test->t_left);
  1693. X        test->t_right = deref_test(test->t_right);
  1694. X        put_trail("deref_test", "finish");
  1695. X        return test;
  1696. X
  1697. Xwhen t_NOT:    test->t_left  = deref_test(test->t_left);
  1698. X        put_trail("deref_test", "finish");
  1699. X        return test;
  1700. X
  1701. Xwhen t_CMD:    test->t_cmd = expand_cmds(test->t_cmd);
  1702. X        put_trail("deref_test", "finish");
  1703. X        return test;
  1704. X
  1705. Xwhen t_MATCH:    deref(test->t_pat, FALSE);
  1706. X        for_list (ptr, test->t_list)
  1707. X        {
  1708. X            pat = (Pat *) ldata(ptr);
  1709. X            deref(pat, FALSE);
  1710. X        }
  1711. X
  1712. X        put_trail("deref_test", "finish");
  1713. X        return test;
  1714. X
  1715. Xwhen t_LIST:    deref(test->t_pat, FALSE);
  1716. X        newlist = makelist0();
  1717. X        for_list (ptr, test->t_list)
  1718. X        {
  1719. X            pat = (Pat *) ldata(ptr);
  1720. X            if (! pat->p_cmd)
  1721. X                addtail(newlist, pat);            /* na */
  1722. X            else
  1723. X            {
  1724. X                deref(pat, TRUE);
  1725. X                addlist(newlist, break_pat(pat));    /* na */
  1726. X            }
  1727. X        }
  1728. X
  1729. X        test->t_list = newlist;
  1730. X        put_trail("deref_test", "finish");
  1731. X        return test;
  1732. X
  1733. Xwhen t_EXIST:    deref(test->t_pat, FALSE);
  1734. X        put_trail("deref_test", "finish");
  1735. X        return test;
  1736. X
  1737. Xwhen t_CANDO:    deref(test->t_pat, FALSE);
  1738. X        put_trail("deref_test", "finish");
  1739. X        return test;
  1740. X
  1741. Xwhen t_OK:    deref(test->t_pat, FALSE);
  1742. X        put_trail("deref_test", "finish");
  1743. X        return test;
  1744. X
  1745. Xotherwise:    printf("cake internal error: bad test type %x in deref_test\n", test->t_kind);
  1746. X        put_trail("deref_test", "finish");
  1747. X        return (Test *) NULL;
  1748. X    }
  1749. X
  1750. X    put_trail("deref_test", "finish");
  1751. X    return (Test *) NULL;
  1752. X}
  1753. X
  1754. XAct *
  1755. Xprep_act(text)
  1756. Xreg    char    *text;
  1757. X{
  1758. X    reg    Act    *act;
  1759. X    reg    char    *s;
  1760. X
  1761. X    act = make(Act);
  1762. X    act->a_flag = 0;
  1763. X
  1764. X    /* strip trailing space - there is at least the newline */
  1765. X    for (s = text+strlen(text)-1; isspace(*s); s--)
  1766. X        *s = '\0';
  1767. X
  1768. X    /* put just the newline back */
  1769. X    strcat(s, "\n");
  1770. X
  1771. X    /* strip spaces before flags */
  1772. X    for (s = text; isspace(*s); s++)
  1773. X        ;
  1774. X
  1775. X    /* process the flags */
  1776. X    for (; *s != '\0'; s++)
  1777. X        if (*s == '@')
  1778. X            set_act(act, af_SILENT);
  1779. X        or (*s == '!')
  1780. X            set_act(act, af_SYSTEM);
  1781. X        or (*s == '-')
  1782. X            set_act(act, af_IGNORE);
  1783. X        or (*s == '+')
  1784. X            set_act(act, af_MINUSN);
  1785. X        else
  1786. X            break;
  1787. X
  1788. X    /* strip spaces after flags */
  1789. X    for (; isspace(*s); s++)
  1790. X        ;
  1791. X
  1792. X    act->a_str = new_name(s);
  1793. X    return act;
  1794. X}
  1795. X
  1796. XAct *
  1797. Xprep_script(first_act, middle_act, last_act)
  1798. Xreg    Act    *first_act, *last_act;
  1799. Xreg    List    *middle_act;
  1800. X{
  1801. X    reg    List    *ptr;
  1802. X    reg    Act    *act;
  1803. X    reg    char    *s;
  1804. X    char        buf[MAXSCRIPT];
  1805. X
  1806. X    buf[0] = '\0';
  1807. X    /* handle the first action */
  1808. X    for (s = first_act->a_str+1; *s == ' ' || *s == '\t'; s++)
  1809. X        ;
  1810. X
  1811. X    if (strdiff(s, "\n"))
  1812. X        strcat(buf, s);
  1813. X
  1814. X    /* handle the middle actions, if any */
  1815. X    for_list (ptr, middle_act)
  1816. X    {
  1817. X        act = (Act *) ldata(ptr);
  1818. X        strcat(buf, act->a_str);
  1819. X    }
  1820. X
  1821. X    /* handle the last action as the first */
  1822. X    for (s = last_act->a_str+1; *s == ' ' || *s == '\t'; s++)
  1823. X        ;
  1824. X
  1825. X    if (strdiff(s, "\n"))
  1826. X        strcat(buf, s);
  1827. X
  1828. X    /* check for overflow */
  1829. X    if (strlen(buf) > MAXSCRIPT)
  1830. X    {
  1831. X        printf("cake: script too long\n");
  1832. X        printf("%s", buf);
  1833. X        exit_cake(FALSE);
  1834. X    }
  1835. X
  1836. X    first_act->a_str = new_name(buf);
  1837. X    set_act(first_act, af_SCRIPT);
  1838. X    return first_act;
  1839. X}
  1840. SHAR_EOF
  1841. if test 11376 -ne "`wc -c < 'entry.c'`"
  1842. then
  1843.     echo shar: "error transmitting 'entry.c'" '(should have been 11376 characters)'
  1844. fi
  1845. fi
  1846. echo shar: "extracting 'error.c'" '(2454 characters)'
  1847. if test -f 'error.c'
  1848. then
  1849.     echo shar: "will not over-write existing file 'error.c'"
  1850. else
  1851. sed 's/^X//' << \SHAR_EOF > 'error.c'
  1852. X/*
  1853. X**    Error handling module.
  1854. X*/
  1855. X
  1856. Xstatic    char
  1857. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/error.c,v 1.15 87/10/05 20:14:20 zs Exp $";
  1858. X
  1859. X#include    "cake.h"
  1860. X
  1861. X/*
  1862. X**    This function prints out the history of errors
  1863. X**    that prevent the proper update of the given node.
  1864. X*/
  1865. X
  1866. Xtrace_errs(node)
  1867. Xreg    Node    *node;
  1868. X{
  1869. X    reg    List    *ptr;
  1870. X    reg    Node    *bnode;
  1871. X
  1872. X    if (on_node(node, nf_TRACED))
  1873. X        return;
  1874. X
  1875. X    set_node(node, nf_TRACED);
  1876. X    for_list (ptr, node->n_badguys)
  1877. X    {
  1878. X        bnode = (Node *) ldata(ptr);
  1879. X        trace_errs(bnode);
  1880. X    }
  1881. X
  1882. X    if (strdiff(node->n_name, CHASEROOT))
  1883. X        printf("%s", node->n_msg);
  1884. X}
  1885. X
  1886. X/*
  1887. X**    This function adds msg to the list of error messages
  1888. X**    to be printed by trace_errs for the given node.
  1889. X*/
  1890. X
  1891. Xadd_error(node, msg, badguys, iserror)
  1892. Xreg    Node    *node;
  1893. Xreg    char    *msg;
  1894. Xreg    List    *badguys;
  1895. Xreg    int    iserror;
  1896. X{
  1897. X    char    buf[MAXSIZE];
  1898. X
  1899. X    if (node->n_msg == NULL)
  1900. X        node->n_msg = "";
  1901. X
  1902. X    if (iserror)
  1903. X        set_node(node, nf_ERR);
  1904. X
  1905. X    sprintf(buf, "%scake: %s\n", node->n_msg, msg);
  1906. X    if (strlen(buf) >= MAXSIZE)
  1907. X    {
  1908. X        fprintf(stderr, "cake internal error: buffer overflow in add_error\n");
  1909. X        exit_cake(FALSE);
  1910. X    }
  1911. X
  1912. X    node->n_msg = new_name(buf);
  1913. X    node->n_badguys = addlist(node->n_badguys, badguys);
  1914. X}
  1915. X
  1916. Xchar *
  1917. Xfind_circle(name)
  1918. Xreg    char    *name;
  1919. X{
  1920. X    extern    int    goal_stackp;
  1921. X    extern    char    *goal_stack[];
  1922. X    char        buf[MAXSIZE];
  1923. X    reg    int    i;
  1924. X
  1925. X    cdebug("stackp = %d\n", goal_stackp);
  1926. X    cdebug("looking for %s\n", goal_stack[goal_stackp-1]);
  1927. X
  1928. X    if (goal_stack[goal_stackp-1] == name)
  1929. X        return "directly";
  1930. X
  1931. X    for (i = 0; i < goal_stackp; i++)
  1932. X    {
  1933. X        cdebug("checking %d: %s\n", i, goal_stack[i]);
  1934. X        if (goal_stack[i] == name)
  1935. X        {
  1936. X            cdebug("hit\n");
  1937. X            strcpy(buf, "through");
  1938. X            for (; i < goal_stackp; i++)
  1939. X            {
  1940. X                strcat(buf, " ");
  1941. X                strcat(buf, goal_stack[i]);
  1942. X            }
  1943. X
  1944. X            if (strlen(buf) >= MAXSIZE)
  1945. X            {
  1946. X                fprintf(stderr, "cake internal error: buffer overflow in find_circle\n");
  1947. X                exit_cake(FALSE);
  1948. X            }
  1949. X
  1950. X            return new_name(buf);
  1951. X        }
  1952. X    }
  1953. X
  1954. X    fprintf(stderr, "cake internal error: no circularity in find_circle\n");
  1955. X    exit_cake(TRUE);
  1956. X    return "";        /* to satisfy lint */
  1957. X}
  1958. X
  1959. Xchar *
  1960. Xlist_names(list)
  1961. Xreg    List    *list;        /* of Node    */
  1962. X{
  1963. X    reg    List    *ptr;
  1964. X    reg    Node    *node;
  1965. X    reg    char    *sep;
  1966. X    char        buf[MAXSIZE];
  1967. X
  1968. X    buf[0] = '\0';
  1969. X    sep = "";
  1970. X    for_list (ptr, list)
  1971. X    {
  1972. X        node = (Node *) ldata(ptr);
  1973. X        strcat(buf, sep);
  1974. X        strcat(buf, node->n_name);
  1975. X        sep = " ";
  1976. X    }
  1977. X
  1978. X    if (strlen(buf) >= MAXSIZE)
  1979. X    {
  1980. X        fprintf(stderr, "cake internal error: buffer overflow in list_names\n");
  1981. X        exit_cake(FALSE);
  1982. X    }
  1983. X
  1984. X    return new_name(buf);
  1985. X}
  1986. SHAR_EOF
  1987. if test 2454 -ne "`wc -c < 'error.c'`"
  1988. then
  1989.     echo shar: "error transmitting 'error.c'" '(should have been 2454 characters)'
  1990. fi
  1991. fi
  1992. echo shar: "extracting 'expand.c'" '(5774 characters)'
  1993. if test -f 'expand.c'
  1994. then
  1995.     echo shar: "will not over-write existing file 'expand.c'"
  1996. else
  1997. sed 's/^X//' << \SHAR_EOF > 'expand.c'
  1998. X/*
  1999. X**    Module to expand out commands in patterns and actions.
  2000. X*/
  2001. X
  2002. Xstatic    char
  2003. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/expand.c,v 1.14 86/07/19 12:23:01 zs Exp $";
  2004. X
  2005. X#include    "cake.h"
  2006. X#include    <ctype.h>
  2007. X
  2008. X/*
  2009. X**    Expand any commands in actions. Doing this here instead of
  2010. X**    in the shell saves time because of cake's command cache.
  2011. X*/
  2012. X
  2013. Xchar *
  2014. Xexpand_cmds(str)
  2015. Xreg    char    *str;
  2016. X{
  2017. X    extern    char    *get_output();
  2018. X    reg    char    *s;
  2019. X    reg    int    n, cmds, offset;
  2020. X    reg    int    stackp;
  2021. X    reg    char    *rightbr;
  2022. X    char        *leftbr_stack[MAXNEST];
  2023. X    char        *nextbr_stack[MAXNEST];
  2024. X    char        copybuf[MAXSIZE], buf[MAXSIZE];
  2025. X    reg    char    *result;
  2026. X
  2027. X    if (index(str, '[') == NULL)
  2028. X        return str;
  2029. X
  2030. X    put_trail("expand_cmds", "start");
  2031. X    cmds = 0;
  2032. X    stackp = 0;
  2033. X    if (strlen(str) >= MAXSIZE)
  2034. X    {
  2035. X        fprintf(stderr, "cake internal error: command too long %s\n", str);
  2036. X        exit_cake(FALSE);
  2037. X    }
  2038. X
  2039. X    strcpy(copybuf, str);
  2040. X    leftbr_stack[stackp] = copybuf;
  2041. X    nextbr_stack[stackp] = NULL;
  2042. X
  2043. X    /* Leftbr_stack[stackp] and rightbr enclose commands       */
  2044. X    /* for stackp > 0; for stackp == 0 they enclose the string */
  2045. X    /* Nextbr_stack gives the beginning of the next segment       */
  2046. X    /* after the corresponding leftbr; == 0 if not known (yet) */
  2047. X    /* The top entry on the stack always has nextbr == NULL       */
  2048. X
  2049. X    for (s = copybuf; s[0] != '\0'; s++)
  2050. X    {
  2051. X        if (s[0] == '[' && s[1] == '[')
  2052. X        {
  2053. X            nextbr_stack[stackp] = s;
  2054. X            if (++stackp >= MAXNEST)
  2055. X            {
  2056. X                fprintf(stderr, "cake internal error: command nesting level too deep\n");
  2057. X                exit_cake(FALSE);
  2058. X            }
  2059. X
  2060. X            leftbr_stack[stackp] = s;
  2061. X            nextbr_stack[stackp] = NULL;
  2062. X            s++;    /* avoid problems with [[[cmd]] ... */
  2063. X        }
  2064. X        or (s[0] == ']' && s[1] == ']')
  2065. X        {
  2066. X            if (stackp <= 0)
  2067. X                continue;
  2068. X
  2069. X            cmds++;
  2070. X            rightbr = s;
  2071. X
  2072. X            leftbr_stack[stackp][0] = '\0';
  2073. X            leftbr_stack[stackp][1] = '\0';
  2074. X            rightbr[0] = '\0';
  2075. X            rightbr[1] = '\0';
  2076. X
  2077. X            result = get_output(new_name(leftbr_stack[stackp]+2));
  2078. X            cdebug("expansion [[%s]] => [[%s]]\n", leftbr_stack[stackp]+2, result);
  2079. X
  2080. X            segcpy(buf, leftbr_stack[stackp-1], nextbr_stack[stackp-1]);
  2081. X            strcat(buf, result);
  2082. X            offset = strlen(buf) - 1;
  2083. X            strcat(buf, rightbr+2);
  2084. X
  2085. X            if (strlen(buf) >= MAXSIZE)
  2086. X            {
  2087. X                fprintf(stderr, "cake: expansion result '%s' is too long\n", buf);
  2088. X                exit_cake(FALSE);
  2089. X            }
  2090. X
  2091. X            stackp--;
  2092. X            leftbr_stack[stackp] = new_name(buf);
  2093. X            nextbr_stack[stackp] = NULL;
  2094. X
  2095. X            /* start next iteration with the */
  2096. X            /* first character after the ]]  */
  2097. X            s = leftbr_stack[stackp] + offset;
  2098. X        }
  2099. X        or (s[0] == '\\')
  2100. X        {
  2101. X            /* don't check next char */
  2102. X            if (s[1] != '\0')
  2103. X                s++; 
  2104. X        }
  2105. X    }
  2106. X
  2107. X#ifdef    CAKEDEBUG
  2108. X    if (entrydebug)
  2109. X        printf("after expand_cmds: [[%s]]\n", str);
  2110. X#endif
  2111. X
  2112. X    if (cmds <= 0)
  2113. X    {
  2114. X        put_trail("expand_cmds", "finish");
  2115. X        return str;
  2116. X    }
  2117. X    or (stackp == 0)
  2118. X    {
  2119. X        put_trail("expand_cmds", "finish");
  2120. X        return leftbr_stack[0];
  2121. X    }
  2122. X
  2123. X    segcpy(buf, leftbr_stack[0], nextbr_stack[0]);
  2124. X    for (n = 1; n <= stackp; n++)
  2125. X        segcat(buf, leftbr_stack[n], nextbr_stack[n]);
  2126. X
  2127. X    if (strlen(buf) >= MAXSIZE)
  2128. X    {
  2129. X        fprintf(stderr, "cake: expansion result '%s' is too long\n", buf);
  2130. X        exit_cake(FALSE);
  2131. X    }
  2132. X
  2133. X    put_trail("expand_cmds", "finish");
  2134. X    return new_name(buf);
  2135. X}
  2136. X
  2137. Xsegcpy(target, left, right)
  2138. Xreg    char    *target, *left, *right;
  2139. X{
  2140. X    reg    int    i;
  2141. X    reg    char    *s;
  2142. X
  2143. X    if (right == NULL)
  2144. X        strcpy(target, left);
  2145. X    else
  2146. X    {
  2147. X        for (s = left, i = 0; s != right; s++, i++)
  2148. X            target[i] = *s;
  2149. X
  2150. X        target[i] = '\0';
  2151. X    }
  2152. X}
  2153. X
  2154. Xsegcat(target, left, right)
  2155. Xreg    char    *target, *left, *right;
  2156. X{
  2157. X    reg    int    i;
  2158. X    reg    char    *s;
  2159. X
  2160. X    if (right == NULL)
  2161. X        strcat(target, left);
  2162. X    else
  2163. X    {
  2164. X        for (s = left, i = strlen(target); s != right; s++, i++)
  2165. X            target[i] = *s;
  2166. X
  2167. X        target[i] = '\0';
  2168. X    }
  2169. X}
  2170. X
  2171. X/*
  2172. X**    Execute the given command and return its output.
  2173. X**    It is a fatal error for the command to terminate abnormally.
  2174. X*/
  2175. X
  2176. Xchar *
  2177. Xget_output(cmd)
  2178. Xreg    char    *cmd;
  2179. X{
  2180. X    extern    char    *mktemp();
  2181. X    extern    char    *get_out();
  2182. X    extern    char    *flatten();
  2183. X    extern    int    cake_proc();
  2184. X    extern    Wait    cake_wait();
  2185. X    char        buf[MAXSIZE];
  2186. X    Wait        code;
  2187. X    reg    char    *out_filename;
  2188. X    reg    FILE    *fp;
  2189. X    reg    int    i, c;
  2190. X    reg    int    pid;
  2191. X    reg    char    *s, *result;
  2192. X
  2193. X    put_trail("get_output", "start");
  2194. X    cdebug("get_output of [%s]\n", cmd);
  2195. X
  2196. X    /* see if we have tried this command before */
  2197. X    if ((result = get_out(cmd)) != NULL)
  2198. X    {
  2199. X        cdebug("cache yields [%s]\n", result);
  2200. X        put_trail("get_output", "early finish");
  2201. X        return result;
  2202. X    }
  2203. X
  2204. X    out_filename = get_newname();
  2205. X    pid = cake_proc(cmd, Exec, out_filename, (Node *) NULL, (int (*)()) NULL, (List *) NULL);
  2206. X    code = cake_wait(pid);
  2207. X    if (code.w_status != 0 && ! zflag)
  2208. X    {
  2209. X        printf("cake, %s: nonzero exit status\n", cmd);
  2210. X        exit_cake(FALSE);
  2211. X    }
  2212. X
  2213. X    if ((fp = fopen(out_filename, "r")) == NULL)
  2214. X    {
  2215. X        sprintf(scratchbuf, "cake system error, fopen %s", out_filename);
  2216. X        perror(scratchbuf);
  2217. X        exit_cake(FALSE);
  2218. X    }
  2219. X
  2220. X    /* convert the chars in file fp to a string */
  2221. X    i = 0;
  2222. X    while ((c = getc(fp)) != EOF)
  2223. X        buf[i++] = c;
  2224. X    
  2225. X    buf[i] = '\0';
  2226. X    fclose(fp);
  2227. X    if (MAXSIZE <= i)
  2228. X    {
  2229. X        printf("cake, %s: output too long\n", cmd);
  2230. X        exit_cake(FALSE);
  2231. X    }
  2232. X
  2233. X#ifndef    LEAVE_DIR
  2234. X    cdebug("get_output unlink out_filename %s\n", out_filename);
  2235. X    if (unlink(out_filename) != 0)
  2236. X    {
  2237. X        sprintf(scratchbuf, "cake system error, unlink %s", out_filename);
  2238. X        perror(scratchbuf);
  2239. X    }
  2240. X#endif
  2241. X
  2242. X    /* save the result for posterity */
  2243. X    s = new_name(flatten(buf));
  2244. X    new_out(cmd, s);
  2245. X    cdebug("put result [%s] into cache\n", s);
  2246. X    put_trail("get_output", "finish");
  2247. X    return s;
  2248. X}
  2249. X
  2250. X/*
  2251. X**    Flatten the output of commands by converting newlines to spaces
  2252. X**    and by removing blanks around the edges.
  2253. X*/
  2254. X
  2255. Xchar *
  2256. Xflatten(str)
  2257. Xreg    char    *str;
  2258. X{
  2259. X    reg    char    *s;
  2260. X
  2261. X    /* convert newlines (and formfeeds) to spaces */
  2262. X    for (s = str; *s != '\0'; s++)
  2263. X        if (*s == '\n' || *s == '\f')
  2264. X            *s = ' ';
  2265. X
  2266. X    /* remove blanks around the edges */
  2267. X    for (s = str+strlen(str)-1; str <= s && isspace(*s); s--)
  2268. X        *s = '\0';
  2269. X    for (s = str; *s != '\0' && isspace(*s); s++)
  2270. X        ;
  2271. X
  2272. X    return s;
  2273. X}
  2274. SHAR_EOF
  2275. if test 5774 -ne "`wc -c < 'expand.c'`"
  2276. then
  2277.     echo shar: "error transmitting 'expand.c'" '(should have been 5774 characters)'
  2278. fi
  2279. fi
  2280. echo shar: "extracting 'file.c'" '(12147 characters)'
  2281. if test -f 'file.c'
  2282. then
  2283.     echo shar: "will not over-write existing file 'file.c'"
  2284. else
  2285. sed 's/^X//' << \SHAR_EOF > 'file.c'
  2286. X/*
  2287. X**    File system interface module.
  2288. X*/
  2289. X
  2290. Xstatic    char
  2291. Xrcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/file.c,v 1.14 86/07/19 12:23:08 zs Exp $";
  2292. X
  2293. X#include    "cake.h"
  2294. X#include    <errno.h>
  2295. X#include    <sys/dir.h>
  2296. X#include    <sys/stat.h>
  2297. X#ifndef        ATT
  2298. X#include    <sys/time.h>
  2299. X#endif
  2300. X
  2301. Xtypedef    struct    timeval        Tval;
  2302. Xtypedef    struct    timezone    Tzone;
  2303. Xtypedef    struct    stat        Stat;
  2304. Xtypedef    struct    direct        Dirent;
  2305. X
  2306. Xextern    int    errno;
  2307. X
  2308. Xstatic    char    dir_name[30] = "/tmp/CakeXXXXXX";
  2309. X
  2310. X/*
  2311. X**    Create the directory to be used for all temporary storage.
  2312. X*/
  2313. X
  2314. Xdir_start()
  2315. X{
  2316. X    reg    bool    successful;
  2317. X
  2318. X    mktemp(dir_name);
  2319. X
  2320. X#ifdef    ATT
  2321. X    {
  2322. X        extern    int    cake_proc();
  2323. X        extern    Wait    cake_wait();
  2324. X        reg    int    pid;
  2325. X        Wait        code;
  2326. X
  2327. X        sprintf(scratchbuf, "mkdir %s", dir_name);
  2328. X        pid = cake_proc(new_name(scratchbuf), Exec, (char *) NULL,
  2329. X            (Node *) NULL, (int (*)()) NULL, (List *) NULL);
  2330. X        code = cake_wait(pid);
  2331. X        successful = code.w_status == 0;
  2332. X    }
  2333. X#else
  2334. X    successful = mkdir(dir_name, 0700) == 0;
  2335. X#endif
  2336. X
  2337. X    if (! successful)
  2338. X    {
  2339. X        sprintf(scratchbuf, "cake system error, mkdir %s", dir_name);
  2340. X        perror(scratchbuf);
  2341. X        exit_cake(FALSE);
  2342. X    }
  2343. X
  2344. X#ifdef    ATT
  2345. X    if (chmod(dir_name, 0700) != 0)
  2346. X    {
  2347. X        sprintf(scratchbuf, "cake system error, chmod 700 %s", dir_name);
  2348. X        perror(scratchbuf);
  2349. X        exit_cake(FALSE);
  2350. X    }
  2351. X#endif
  2352. X}
  2353. X
  2354. X/*
  2355. X**    Clean up /tmp when we are finished
  2356. X*/
  2357. X
  2358. Xdir_finish()
  2359. X{
  2360. X#ifndef    LEAVE_DIR
  2361. X#ifdef    ATT
  2362. X    extern    int    cake_proc();
  2363. X    extern    Wait    cake_wait();
  2364. X    reg    int    pid;
  2365. X    Wait        code;
  2366. X
  2367. X    sprintf(scratchbuf, "/bin/rm -fr %s", dir_name);
  2368. X    pid = cake_proc(new_name(scratchbuf), Exec, (char *) NULL,
  2369. X        (Node *) NULL, (int (*)()) NULL, (List *) NULL);
  2370. X    code = cake_wait(pid);
  2371. X    if (code.w_status != 0)
  2372. X    {
  2373. X        fprintf(stderr, "cake system error: cannot remove %s\n", dir_name);
  2374. X        return;
  2375. X    }
  2376. X#else
  2377. X    char        buf[1024];
  2378. X    reg    DIR    *dirp;
  2379. X    reg    Dirent    *dp;
  2380. X    reg    int    nameoffset;
  2381. X
  2382. X    if ((dirp = opendir(dir_name)) == NULL)
  2383. X    {
  2384. X        sprintf(scratchbuf, "cake system error, opendir %s", dir_name);
  2385. X        perror(scratchbuf);
  2386. X        return;
  2387. X    }
  2388. X
  2389. X    strcpy(buf, dir_name);
  2390. X    strcat(buf, "/");
  2391. X    nameoffset = strlen(buf);
  2392. X
  2393. X    for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
  2394. X        if (strdiff(dp->d_name, ".") && strdiff(dp->d_name, ".."))
  2395. X        {
  2396. X            buf[nameoffset] = '\0';
  2397. X            strcat(buf, dp->d_name);
  2398. X            cdebug("dir_finish unlink %s\n", buf);
  2399. X            if (unlink(buf) != 0)
  2400. X            {
  2401. X                sprintf(scratchbuf, "cake system error, unlink %s", buf);
  2402. X                perror(scratchbuf);
  2403. X            }
  2404. X        }
  2405. X
  2406. X    closedir(dirp);
  2407. X
  2408. X    cdebug("rmdir %s\n", dir_name);
  2409. X    if (rmdir(dir_name) != 0)
  2410. X    {
  2411. X        sprintf(scratchbuf, "cake system error, rmdir %s", dir_name);
  2412. X        perror(scratchbuf);
  2413. X    }
  2414. X#endif
  2415. X#endif
  2416. X}
  2417. X
  2418. X/*
  2419. X**    Get a new filename in our private directory.
  2420. X**    These files are used to store shell scripts
  2421. X**    and the output of actions.
  2422. X**
  2423. X**    These names MUST be different from those generated
  2424. X**    by get_savename, so they have different prefixes.
  2425. X*/
  2426. X
  2427. Xchar *
  2428. Xget_newname()
  2429. X{
  2430. X    char        buf[100];
  2431. X    static    int    count = 0;
  2432. X
  2433. X    ++count;
  2434. X    sprintf(buf, "%s/gen_%d", dir_name, count);
  2435. X    return new_name(buf);
  2436. X}
  2437. X
  2438. X/*
  2439. X**    Save a nonvolatile file for later comparison.
  2440. X**    Any slashes in the filename are replaced by colons
  2441. X**    to avoid reference to nonexistent directories.
  2442. X*/
  2443. X
  2444. Xsave_novol(node)
  2445. Xreg    Node    *node;
  2446. X{
  2447. X    char        buf[MAXSIZE];
  2448. X    reg    FILE    *ifp, *ofp;
  2449. X    reg    int    c;
  2450. X
  2451. X    if (nflag)
  2452. X    {
  2453. X        node->n_stime = node->n_rtime;
  2454. X        return;
  2455. X    }
  2456. X
  2457. X    put_trail("save_novol", "start");
  2458. X    cdebug("saving %s\n", node->n_name);
  2459. X    node->n_stime = node->n_rtime;
  2460. X
  2461. X    get_savename(node->n_name, buf);
  2462. X    if ((ifp = fopen(node->n_name, "r")) == NULL)
  2463. X    {
  2464. X        if (errno == ENOENT)
  2465. X        {
  2466. X            cdebug("%s does not exist, considered volatile\n", node->n_name);
  2467. X            reset_node(node, nf_NONVOL);
  2468. X            put_trail("save_novol", "finish");
  2469. X            return;
  2470. X        }
  2471. X
  2472. X        sprintf(scratchbuf, "cake system error, fopen (r) %s", node->n_name);
  2473. X        perror(scratchbuf);
  2474. X        printf("cake: considering %s volatile\n", node->n_name);
  2475. X        reset_node(node, nf_NONVOL);
  2476. X        put_trail("save_novol", "finish");
  2477. X        return;
  2478. X    }
  2479. X
  2480. X    if ((ofp = fopen(buf, "w")) == NULL)
  2481. X    {
  2482. X        sprintf(scratchbuf, "cake system error, fopen (w) %s", buf);
  2483. X        perror(scratchbuf);
  2484. X        printf("cake: considering %s volatile\n", node->n_name);
  2485. X        reset_node(node, nf_NONVOL);
  2486. X        put_trail("save_novol", "finish");
  2487. X        return;
  2488. X    }
  2489. X
  2490. X    while ((c = getc(ifp)) != EOF)
  2491. X        putc(c, ofp);
  2492. X    
  2493. X    fclose(ifp);
  2494. X    fclose(ofp);
  2495. X    put_trail("save_novol", "finish");
  2496. X}
  2497. X
  2498. X/*
  2499. X**    See if the given file has been changed since saved.
  2500. X*/
  2501. X
  2502. Xbool
  2503. Xdiff_novol(node)
  2504. Xreg    Node    *node;
  2505. X{
  2506. X    char        buf[MAXSIZE];
  2507. X    reg    FILE    *i1fp, *i2fp;
  2508. X    reg    int    c;
  2509. X    reg    bool    diff;
  2510. X
  2511. X    if (nflag)
  2512. X        return FALSE;
  2513. X
  2514. X    put_trail("diff_novol", "start");
  2515. X    cdebug("comparing saved copy of %s: ", node->n_name);
  2516. X
  2517. X    get_savename(node->n_name, buf);
  2518. X    if ((i1fp = fopen(node->n_name, "r")) == NULL)
  2519. X    {
  2520. X        sprintf(scratchbuf, "cake system error, fopen (r) %s", node->n_name);
  2521. X        perror(scratchbuf);
  2522. X        printf("cake: considering %s different\n", node->n_name);
  2523. X        reset_node(node, nf_NONVOL);
  2524. X        put_trail("diff_novol", "finish");
  2525. X        return TRUE;;
  2526. X    }
  2527. X
  2528. X    if ((i2fp = fopen(buf, "r")) == NULL)
  2529. X    {
  2530. X        sprintf(scratchbuf, "cake system error, fopen (r) %s", buf);
  2531. X        perror(scratchbuf);
  2532. X        printf("cake: considering %s different\n", node->n_name);
  2533. X        reset_node(node, nf_NONVOL);
  2534. X        put_trail("diff_novol", "finish");
  2535. X        return TRUE;;
  2536. X    }
  2537. X
  2538. X    diff = FALSE;
  2539. X    while ((c = getc(i1fp)) != EOF)
  2540. X        if (getc(i2fp) != c)
  2541. X        {
  2542. X            diff = TRUE;
  2543. X            break;
  2544. X        }
  2545. X    
  2546. X    if (getc(i2fp) != EOF)
  2547. X        diff = TRUE;
  2548. X    
  2549. X    fclose(i1fp);
  2550. X    fclose(i2fp);
  2551. X    cdebug("diff_novol unlink %s\n", buf);
  2552. X    if (unlink(buf) != 0)
  2553. X    {
  2554. X        sprintf(scratchbuf, "cake system error, unlink %s", buf);
  2555. X        perror(scratchbuf);
  2556. X        put_trail("diff_novol", "finish");
  2557. X        return TRUE;
  2558. X    }
  2559. X
  2560. X    cdebug("%s\n", diff? "different": "same");
  2561. X    put_trail("diff_novol", "finish");
  2562. X    return diff;
  2563. X}
  2564. X
  2565. X/*
  2566. X**    Get the the name of the saved copy of the given file.
  2567. X*/
  2568. X
  2569. Xget_savename(name, buf)
  2570. Xreg    char    *name;
  2571. Xreg    char    buf[];
  2572. X{
  2573. X    extern    char    *noslash();
  2574. X
  2575. X    strcpy(buf, dir_name);
  2576. X    strcat(buf, "/save_");
  2577. X    strcat(buf, noslash(name));
  2578. X}
  2579. X
  2580. X/*
  2581. X**    Remove any slashes from a filename.
  2582. X*/
  2583. X
  2584. Xchar *
  2585. Xnoslash(name)
  2586. Xreg    char    *name;
  2587. X{
  2588. X    char        buf[MAXSIZE];
  2589. X    reg    int    i;
  2590. X    reg    char    *s;
  2591. X
  2592. X    i = 0;
  2593. X    for (s = name; *s != '\0'; s++)
  2594. X        if (*s == '/')
  2595. X            buf[i++] = ':';
  2596. X        else
  2597. X            buf[i++] = *s;
  2598. X    
  2599. X    buf[i] = '\0';
  2600. X    return new_name(buf);
  2601. X}
  2602. X
  2603. X/*
  2604. X**    Perform a stat on the given file. The only relevant info
  2605. X**    is the return code, indicating whether the file exists or not
  2606. X**    and its last modify (or status change) date. Note that if a
  2607. X**    file does not exist, it is by definition volatile. An aside
  2608. X**    considers all directories precious.
  2609. X*/
  2610. X
  2611. Xnode_stat(node)
  2612. Xreg    Node    *node;
  2613. X{
  2614. X    extern    int    stat();
  2615. X    Stat        statbuf;
  2616. X
  2617. X    if (node->n_name != (char *) NULL && stat(node->n_name, &statbuf) == 0)
  2618. X    {
  2619. X        set_node(node, nf_EXIST);
  2620. X        if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
  2621. X            set_node(node, nf_PRECIOUS);
  2622. X
  2623. X        node->n_rtime = cflag? statbuf.st_ctime: statbuf.st_mtime;
  2624. X    }
  2625. X    else
  2626. X    {
  2627. X        reset_node(node, nf_EXIST);
  2628. X        reset_node(node, nf_NONVOL);
  2629. X        node->n_rtime = GENESIS;
  2630. X    }
  2631. X}
  2632. X
  2633. X/*
  2634. X**    Restore the previous stat of a nonvol file,
  2635. X**    both in the filesystem and in cake's memory.
  2636. X**    However, make sure that it will not need to be
  2637. X**    remade again and again to discover this anew
  2638. X**    while its ancestors remain the same.
  2639. X*/
  2640. X
  2641. Xnode_resetstat(node)
  2642. Xreg    Node    *node;
  2643. X{
  2644. X    node_stat(node);
  2645. X    if (off_node(node, nf_EXIST))
  2646. X        return;
  2647. X
  2648. X    cake_utimes(node, max(node->n_stime, node->n_utime));
  2649. X    node->n_utime = node->n_rtime;
  2650. X}
  2651. X
  2652. X/*
  2653. X**    Set up the stat of a file as the latest ancestor's,
  2654. X**    both in the filesystem and in cake's memory.
  2655. X*/
  2656. X
  2657. Xnode_setstat(node)
  2658. Xreg    Node    *node;
  2659. X{
  2660. X    extern    time_t    get_youngest();
  2661. X    reg    time_t    youngest;
  2662. X
  2663. X    node_stat(node);
  2664. X    if (off_node(node, nf_EXIST))
  2665. X        return;
  2666. X
  2667. X    youngest = get_youngest(node, FALSE);
  2668. X    if (youngest != node->n_utime && youngest != GENESIS)
  2669. X    {
  2670. X        fprintf(stderr, "cake internal error: youngest is mismatched for %s\n",
  2671. X            node->n_name);
  2672. X        exit_cake(TRUE);
  2673. X    }
  2674. X
  2675. X    cake_utimes(node, node->n_utime);
  2676. X}
  2677. X
  2678. X/*
  2679. X**    Return the time, converting formats.
  2680. X*/
  2681. X
  2682. Xtime_t
  2683. Xcake_gettime()
  2684. X{
  2685. X#ifdef    ATT
  2686. X    extern    long    time();
  2687. X    long        val;
  2688. X
  2689. X    if (time(&val) == -1)
  2690. X    {
  2691. X        sprintf(scratchbuf, "cake system error, time");
  2692. X        perror(scratchbuf);
  2693. X        exit_cake(FALSE);
  2694. X    }
  2695. X
  2696. X    return (time_t) val;
  2697. X#else
  2698. X    Tzone        tzone;
  2699. X    Tval        tval;
  2700. X
  2701. X    if (gettimeofday(&tval, &tzone) != 0)
  2702. X    {
  2703. X        sprintf(scratchbuf, "cake system error, gettimeofday");
  2704. X        perror(scratchbuf);
  2705. X        exit_cake(FALSE);
  2706. X    }
  2707. X
  2708. X    return (time_t) tval.tv_sec;
  2709. X#endif
  2710. X}
  2711. X
  2712. X/*
  2713. X**    Issue the system call utimes after expanding its arguments
  2714. X**    from time_t to Tval. If the time given is GENESIS, use the
  2715. X**    current time instead.
  2716. X*/
  2717. X
  2718. X#ifdef    ATT
  2719. Xtypedef    struct    utimbuf
  2720. X{
  2721. X    time_t    actime;
  2722. X    time_t    modtime;
  2723. X} Utimbuf;
  2724. X#endif
  2725. X
  2726. Xcake_utimes(node, newtime)
  2727. Xreg    Node    *node;
  2728. Xtime_t        newtime;
  2729. X{
  2730. X#ifdef    ATT
  2731. X    extern    int    utime();
  2732. X#else
  2733. X    extern    int    utimes();
  2734. X#endif
  2735. X    extern    int    stat();
  2736. X    Stat        statbuf;
  2737. X#ifdef    ATT
  2738. X    Utimbuf        timbuf;
  2739. X    long        vals[2];
  2740. X#else
  2741. X    Tzone        tzone;
  2742. X    Tval        tvals[2];
  2743. X#endif
  2744. X
  2745. X    cdebug("resetting time for %s to %d, %s",
  2746. X        node->n_name, newtime, ctime(&newtime));
  2747. X
  2748. X#ifdef    ATT
  2749. X    if (time(&vals[0]) == -1)
  2750. X    {
  2751. X        sprintf(scratchbuf, "cake system error, time");
  2752. X        perror(scratchbuf);
  2753. X        exit_cake(FALSE);
  2754. X    }
  2755. X#else
  2756. X    if (gettimeofday(&tvals[0], &tzone) != 0)
  2757. X    {
  2758. X        sprintf(scratchbuf, "cake system error, gettimeofday");
  2759. X        perror(scratchbuf);
  2760. X        exit_cake(FALSE);
  2761. X    }
  2762. X#endif
  2763. X
  2764. X    if (newtime == GENESIS)
  2765. X    {
  2766. X        cdebug("reinterpreting GENESIS\n");
  2767. X#ifdef    ATT
  2768. X        if (time(&vals[1]) == -1)
  2769. X        {
  2770. X            sprintf(scratchbuf, "cake system error, time");
  2771. X            perror(scratchbuf);
  2772. X            exit_cake(FALSE);
  2773. X        }
  2774. X#else
  2775. X        if (gettimeofday(&tvals[1], &tzone) != 0)
  2776. X        {
  2777. X            sprintf(scratchbuf, "cake system error, gettimeofday");
  2778. X            perror(scratchbuf);
  2779. X            exit_cake(FALSE);
  2780. X        }
  2781. X#endif
  2782. X    }
  2783. X    else
  2784. X    {
  2785. X#ifdef    ATT
  2786. X        vals[1] = (long) newtime;
  2787. X#else
  2788. X        tvals[1].tv_sec  = newtime;
  2789. X        tvals[1].tv_usec = 0;
  2790. X#endif
  2791. X    }
  2792. X
  2793. X#ifdef    ATT
  2794. X    timbuf.actime  = vals[0];
  2795. X    timbuf.modtime = vals[1];
  2796. X    node->n_rtime  = vals[1];
  2797. X#else
  2798. X    node->n_rtime  = (time_t) tvals[1].tv_sec;
  2799. X#endif
  2800. X
  2801. X    if (nflag)
  2802. X        return;
  2803. X
  2804. X#ifdef    ATT
  2805. X    if (utime(node->n_name, &timbuf) != 0)
  2806. X#else
  2807. X    if (utimes(node->n_name, tvals) != 0)
  2808. X#endif
  2809. X    {
  2810. X        sprintf(scratchbuf, "cake system error, utime(s) %s", node->n_name);
  2811. X        perror(scratchbuf);
  2812. X        fprintf(stderr, "cake: continuing\n");
  2813. X    }
  2814. X
  2815. X#ifdef    CAKEDEBUG
  2816. X    if (cakedebug)
  2817. X    {
  2818. X        if (stat(node->n_name, &statbuf) != 0)
  2819. X            printf("cannot verify utimes\n");
  2820. X        else
  2821. X        {
  2822. X            print_time("accessed", statbuf.st_atime);
  2823. X            print_time("modified", statbuf.st_mtime);
  2824. X            print_time("changed ", statbuf.st_ctime);
  2825. X        }
  2826. X    }
  2827. X#endif
  2828. X}
  2829. X
  2830. X/*
  2831. X**    See if the given file exists.
  2832. X*/
  2833. X
  2834. Xbool
  2835. Xexist(name)
  2836. Xreg    char    *name;
  2837. X{
  2838. X    Stat    statbuf;
  2839. X
  2840. X    if (stat(name, &statbuf) == 0)
  2841. X        return TRUE;
  2842. X    else
  2843. X        return FALSE;
  2844. X}
  2845. X
  2846. X/*
  2847. X**    Remove the given file.
  2848. X*/
  2849. X
  2850. Xcake_remove(name)
  2851. Xreg    char    *name;
  2852. X{
  2853. X#ifdef    CAREFUL
  2854. X    if (! Xflag)
  2855. X    {
  2856. X        extern    int    getpid();
  2857. X        extern    int    cake_proc();
  2858. X        extern    Wait    cake_wait();
  2859. X        extern    char    *noslash();
  2860. X        reg    int    pid, cakepid;
  2861. X        Stat        statbuf;
  2862. X        Wait        code;
  2863. X        char        buf[80];
  2864. X
  2865. X#ifndef    ATT
  2866. X        if (lstat(name, &statbuf) != 0)
  2867. X        {
  2868. X            sprintf(scratchbuf, "cake system error, lstat %s", name);
  2869. X            perror(scratchbuf);
  2870. X            fprintf(stderr, "cake: continuing\n");
  2871. X            return;
  2872. X        }
  2873. X
  2874. X        if ((statbuf.st_mode & S_IFMT) == S_IFLNK)
  2875. X        {
  2876. X            printf("removing the symbolic link %s\n", name);
  2877. X            cdebug("cake_remove unlink %s\n", name);
  2878. X            if (unlink(name) != 0)
  2879. X            {
  2880. X                sprintf(scratchbuf, "cake system error, unlink %s", name);
  2881. X                perror(scratchbuf);
  2882. X                fprintf(stderr, "cake: continuing\n");
  2883. X            }
  2884. X
  2885. X            return;
  2886. X        }
  2887. X#endif
  2888. X
  2889. X        cakepid = getpid();
  2890. X        printf("moving %s to /tmp\n", name);
  2891. X        sprintf(buf, "mv %s /tmp/%s.%d", name, noslash(name), cakepid);
  2892. X        pid = cake_proc(buf, Exec, (char *) NULL, (Node *) NULL,
  2893. X            (int (*)()) NULL, (List *) NULL);
  2894. X        code = cake_wait(pid);
  2895. X        if (code.w_status != 0)
  2896. X        {
  2897. X            fprintf(stderr, "cake system error: '%s' failed\n", buf);
  2898. X            fprintf(stderr, "cake: continuing\n");
  2899. X            return;
  2900. X        }
  2901. X
  2902. X        sprintf(buf, "/tmp/%s.%d", noslash(name), cakepid);
  2903. X        if (chmod(buf, 0600) != 0)
  2904. X        {
  2905. X            sprintf(scratchbuf, "cake system error, chmod %s", buf);
  2906. X            perror(scratchbuf);
  2907. X            fprintf(stderr, "cake: continuing\n");
  2908. X            return;
  2909. X        }
  2910. X
  2911. X        return;
  2912. X    }
  2913. X#endif
  2914. X
  2915. X    cdebug("cake_remove unlink %s\n", name);
  2916. X    if (unlink(name) != 0)
  2917. X    {
  2918. X        sprintf(scratchbuf, "cake system error, unlink %s", name);
  2919. X        perror(scratchbuf);
  2920. X        fprintf(stderr, "cake: continuing\n");
  2921. X    }
  2922. X}
  2923. SHAR_EOF
  2924. if test 12147 -ne "`wc -c < 'file.c'`"
  2925. then
  2926.     echo shar: "error transmitting 'file.c'" '(should have been 12147 characters)'
  2927. fi
  2928. fi
  2929. exit 0
  2930. #    End of shell archive
  2931.